diff --git a/README.md b/README.md
index 0a6a095f92..0899e71fb5 100644
--- a/README.md
+++ b/README.md
@@ -63,3 +63,23 @@ Type list to list all vouchers.
- [x] 고객이 어떤 바우처를 보유하고 있는지 조회할 수 있어야 합니다.
- [x] 고객이 보유한 바우처를 제거할 수 있어야 합니다.
- [x] 특정 바우처를 보유한 고객을 조회할 수 있어야 합니다.
+
+### 3주차 미션
+
+**3-1**
+
+- [x] Spring MVC를 적용해서 thymeleaf 템플릿을 설정해보세요.
+- [x] 커맨드로 지원했던 기능을 thymeleaf를 이용해서 관리페이지를 만들고 다음 기능을 지원가능하게 해보세요
+ - [x] 조회페이지
+ - [x] 상세페이지
+ - [x] 입력페이지
+ - [x] 삭제기능
+
+**3-2**
+
+- [ ] Spring MVC를 적용해서 JSON과 XML을 지원하는 REST API를 개발해보세요
+ - [ ] 전체 조회기능
+ - [ ] 조건별 조회기능 (바우처 생성기간 및 특정 할인타입별)
+ - [ ] 바우처 추가기능
+ - [ ] 바우처 삭제기능
+ - [ ] 바우처 아이디로 조회 기능
diff --git a/build.gradle b/build.gradle
index e8d564472a..92ce216994 100644
--- a/build.gradle
+++ b/build.gradle
@@ -19,6 +19,9 @@ dependencies {
implementation 'org.springframework.boot:spring-boot-starter'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
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-validation'
runtimeOnly 'com.h2database:h2'
diff --git a/src/main/java/com/programmers/springweekly/controller/CustomErrorController.java b/src/main/java/com/programmers/springweekly/controller/CustomErrorController.java
new file mode 100644
index 0000000000..e4ccce5c62
--- /dev/null
+++ b/src/main/java/com/programmers/springweekly/controller/CustomErrorController.java
@@ -0,0 +1,31 @@
+package com.programmers.springweekly.controller;
+
+import jakarta.servlet.RequestDispatcher;
+import jakarta.servlet.http.HttpServletRequest;
+import org.springframework.boot.web.servlet.error.ErrorController;
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.Model;
+import org.springframework.web.bind.annotation.GetMapping;
+
+@Controller
+public class CustomErrorController implements ErrorController {
+
+ // ControllerAdvice로 처리되지 않는 서블릿 수준의 예외와 404 에러 처리
+ @GetMapping("/error")
+ public String errorThrow(HttpServletRequest httpServletRequest, Model model) {
+ Integer errorStatusCode = (Integer) httpServletRequest.getAttribute(RequestDispatcher.ERROR_STATUS_CODE);
+ String errorMessage = (String) httpServletRequest.getAttribute(RequestDispatcher.ERROR_MESSAGE);
+
+ model.addAttribute("errorCode", errorStatusCode);
+
+ if (errorStatusCode == 404) {
+ model.addAttribute("errorMsg", "요청하신 페이지를 찾을 수 없습니다.");
+ return "errorPage";
+ }
+
+ model.addAttribute("errorMsg", errorMessage);
+
+ return "errorPage";
+ }
+
+}
diff --git a/src/main/java/com/programmers/springweekly/controller/CustomerViewController.java b/src/main/java/com/programmers/springweekly/controller/CustomerViewController.java
new file mode 100644
index 0000000000..55bdda8e78
--- /dev/null
+++ b/src/main/java/com/programmers/springweekly/controller/CustomerViewController.java
@@ -0,0 +1,65 @@
+package com.programmers.springweekly.controller;
+
+import com.programmers.springweekly.dto.customer.request.CustomerCreateRequest;
+import com.programmers.springweekly.dto.customer.response.CustomerListResponse;
+import com.programmers.springweekly.dto.customer.response.CustomerResponse;
+import com.programmers.springweekly.service.CustomerService;
+import jakarta.validation.Valid;
+import java.util.UUID;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.Model;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+
+@Controller
+@RequiredArgsConstructor
+@RequestMapping("/view/customer")
+public class CustomerViewController {
+
+ private final CustomerService customerService;
+
+ @GetMapping
+ public String getMenuPage() {
+ return "customer/menu";
+ }
+
+ @GetMapping("/save")
+ public String getCreatePage() {
+ return "customer/create";
+ }
+
+ @PostMapping("/save")
+ public String save(@Valid CustomerCreateRequest customerCreateRequest) {
+ customerService.save(customerCreateRequest);
+
+ return "customer/menu";
+ }
+
+ @GetMapping("/findAll")
+ public String getFindAllPage(Model model) {
+ CustomerListResponse customerListResponse = customerService.findAll();
+ model.addAttribute("customerList", customerListResponse.getCustomerList());
+
+ return "customer/findAll";
+ }
+
+ @GetMapping("/find/{id}")
+ public String findById(@PathVariable("id") UUID customerId, Model model) {
+ CustomerResponse customerResponse = customerService.findById(customerId);
+ model.addAttribute("customer", customerResponse);
+
+ return "customer/find";
+ }
+
+ @DeleteMapping("/delete/{id}")
+ public String deleteById(@PathVariable("id") UUID customerId) {
+ customerService.deleteById(customerId);
+
+ return "redirect:/view/customer/find";
+ }
+
+}
diff --git a/src/main/java/com/programmers/springweekly/controller/HomeController.java b/src/main/java/com/programmers/springweekly/controller/HomeController.java
new file mode 100644
index 0000000000..d722ad6caa
--- /dev/null
+++ b/src/main/java/com/programmers/springweekly/controller/HomeController.java
@@ -0,0 +1,13 @@
+package com.programmers.springweekly.controller;
+
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.GetMapping;
+
+@Controller
+public class HomeController {
+
+ @GetMapping("/")
+ public String home() {
+ return "home";
+ }
+}
diff --git a/src/main/java/com/programmers/springweekly/controller/VoucherController.java b/src/main/java/com/programmers/springweekly/controller/VoucherController.java
index 5320093a4b..df75c6b264 100644
--- a/src/main/java/com/programmers/springweekly/controller/VoucherController.java
+++ b/src/main/java/com/programmers/springweekly/controller/VoucherController.java
@@ -19,7 +19,7 @@ public class VoucherController {
public void save(VoucherCreateRequest voucherCreateRequest) {
VoucherValidator.validateVoucher(
voucherCreateRequest.getVoucherType(),
- String.valueOf(voucherCreateRequest.getDiscountAmount())
+ voucherCreateRequest.getDiscountAmount()
);
voucherService.save(voucherCreateRequest);
@@ -28,7 +28,7 @@ public void save(VoucherCreateRequest voucherCreateRequest) {
public void update(VoucherUpdateRequest voucherUpdateRequest) {
VoucherValidator.validateVoucher(
voucherUpdateRequest.getVoucherType(),
- String.valueOf(voucherUpdateRequest.getDiscountAmount())
+ voucherUpdateRequest.getDiscountAmount()
);
voucherService.update(voucherUpdateRequest);
diff --git a/src/main/java/com/programmers/springweekly/controller/VoucherViewController.java b/src/main/java/com/programmers/springweekly/controller/VoucherViewController.java
new file mode 100644
index 0000000000..cf49f6458c
--- /dev/null
+++ b/src/main/java/com/programmers/springweekly/controller/VoucherViewController.java
@@ -0,0 +1,71 @@
+package com.programmers.springweekly.controller;
+
+import com.programmers.springweekly.dto.voucher.request.VoucherCreateRequest;
+import com.programmers.springweekly.dto.voucher.response.VoucherListResponse;
+import com.programmers.springweekly.dto.voucher.response.VoucherResponse;
+import com.programmers.springweekly.service.VoucherService;
+import com.programmers.springweekly.util.validator.VoucherValidator;
+import jakarta.validation.Valid;
+import java.util.UUID;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.Model;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+
+@Controller
+@RequiredArgsConstructor
+@RequestMapping("/view/voucher")
+public class VoucherViewController {
+
+ private final VoucherService voucherService;
+
+ @GetMapping
+ public String getMenuPage() {
+ return "voucher/menu";
+ }
+
+ @GetMapping("/save")
+ public String getCreatePage() {
+ return "voucher/create";
+ }
+
+ @PostMapping("/save")
+ public String save(@Valid VoucherCreateRequest voucherCreateRequest) {
+ VoucherValidator.validateVoucher(
+ voucherCreateRequest.getVoucherType(),
+ voucherCreateRequest.getDiscountAmount()
+ );
+
+ voucherService.save(voucherCreateRequest);
+
+ return "voucher/menu";
+ }
+
+ @GetMapping("/findAll")
+ public String getFindAllPage(Model model) {
+ VoucherListResponse voucherListResponse = voucherService.findAll();
+ model.addAttribute("voucherList", voucherListResponse.getVoucherList());
+
+ return "voucher/findAll";
+ }
+
+ @GetMapping("/find/{id}")
+ public String findById(@PathVariable("id") UUID voucherId, Model model) {
+ VoucherResponse voucherResponse = voucherService.findById(voucherId);
+ model.addAttribute("voucher", voucherResponse);
+
+ return "voucher/find";
+ }
+
+ @DeleteMapping("/delete/{id}")
+ public String deleteById(@PathVariable("id") UUID voucherId) {
+ voucherService.deleteById(voucherId);
+
+ return "redirect:/view/voucher/find";
+ }
+
+}
diff --git a/src/main/java/com/programmers/springweekly/docs/specification.md b/src/main/java/com/programmers/springweekly/docs/specification.md
index 1642eedc01..f8d8d0da8b 100644
--- a/src/main/java/com/programmers/springweekly/docs/specification.md
+++ b/src/main/java/com/programmers/springweekly/docs/specification.md
@@ -206,4 +206,46 @@ blacklist
- 바우처 지갑에 있는 모든 리스트 조회(findAll)
- 테스트 코드 구현
+
+
+### 3-1 Thymeleaf를 이용하여 바우처 관리페이지 구현
+
+### 요약
+
+- 고객, 바우처 CREATE, UPDATE, DELETE Web Controller 구현
+- CreateRequestDto에 Validation 적용.
+- Thymeleaf를 이용한 페이지 생성
+- ControllerAdvice를 통한 Global 예외 처리
+
+### Voucher(web)
+
+- 바우처 입력 기능
+- 바우처 삭제 기능
+- 바우처 전체 조회, 상세 조회 기능
+
+### Customer(web)
+
+- 고객 입력 기능
+- 고객 삭제 기능
+- 고객 전체 조회, 상세 조회 기능
+
+### Validation
+
+- Spring에서 제공하는 Validation을 사용하여 DTO단에서 RequestBody 값을 검증
+
+### ControllerAdvice
+
+- Controller, Serivce, Repository 등 Controller 하위 단에서 발생한 예외를 전역으로 잡는 ExceptionHandler 클래스 생성
+- 프로그램 내에서 발생할 것 같은 예외들을 모두 구분하여 로깅하고, 메세지를 페이지로 발송하여 Error페이지에 출력
+- 예외 별 상태 코드 적용
+- 발생할 것 같은 예외들을 모두 잡고 예상치 못한 예외가 발생했을 때 프로그램이 꺼지지 않도록 제일 하위에 최상위 Exception으로 예외 처리
+
+### 웹 동작 화면(정상)
+
+
+### 웹 동작 화면(에러)
+
+
+
+
diff --git a/src/main/java/com/programmers/springweekly/domain/voucher/FixedAmountVoucher.java b/src/main/java/com/programmers/springweekly/domain/voucher/FixedAmountVoucher.java
index 9f0a89edc9..6e25864146 100644
--- a/src/main/java/com/programmers/springweekly/domain/voucher/FixedAmountVoucher.java
+++ b/src/main/java/com/programmers/springweekly/domain/voucher/FixedAmountVoucher.java
@@ -11,7 +11,7 @@ public class FixedAmountVoucher implements Voucher {
public FixedAmountVoucher(UUID voucherId, long discountAmount) {
VoucherValidator.validateVoucher(
VoucherType.FIXED,
- String.valueOf(discountAmount)
+ discountAmount
);
this.voucherId = voucherId;
diff --git a/src/main/java/com/programmers/springweekly/domain/voucher/PercentDiscountVoucher.java b/src/main/java/com/programmers/springweekly/domain/voucher/PercentDiscountVoucher.java
index 8fefead89e..49b52bda4b 100644
--- a/src/main/java/com/programmers/springweekly/domain/voucher/PercentDiscountVoucher.java
+++ b/src/main/java/com/programmers/springweekly/domain/voucher/PercentDiscountVoucher.java
@@ -11,7 +11,7 @@ public class PercentDiscountVoucher implements Voucher {
public PercentDiscountVoucher(UUID voucherId, long discountAmount) {
VoucherValidator.validateVoucher(
VoucherType.PERCENT,
- String.valueOf(discountAmount)
+ discountAmount
);
this.voucherId = voucherId;
diff --git a/src/main/java/com/programmers/springweekly/dto/customer/request/CustomerCreateRequest.java b/src/main/java/com/programmers/springweekly/dto/customer/request/CustomerCreateRequest.java
index 29d48716b0..6261d7c7f5 100644
--- a/src/main/java/com/programmers/springweekly/dto/customer/request/CustomerCreateRequest.java
+++ b/src/main/java/com/programmers/springweekly/dto/customer/request/CustomerCreateRequest.java
@@ -1,14 +1,25 @@
package com.programmers.springweekly.dto.customer.request;
import com.programmers.springweekly.domain.customer.CustomerType;
+import jakarta.validation.constraints.Email;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+import jakarta.validation.constraints.Pattern;
import lombok.Builder;
import lombok.Getter;
@Getter
public class CustomerCreateRequest {
+ @NotBlank(message = "이름은 필수 입력 값입니다.")
+ @Pattern(regexp = "^[a-zA-Z]*$", message = "이름은 영어로만 입력되어야 합니다.")
private String customerName;
+
+ @Email(message = "이메일 양식에 맞춰서 입력해주세요.")
+ @NotBlank(message = "이메일은 필수 입력 값입니다.")
private String customerEmail;
+
+ @NotNull(message = "타입은 필수 입력 값입니다.")
private CustomerType customerType;
@Builder
@@ -17,5 +28,5 @@ public CustomerCreateRequest(String customerName, String customerEmail, Customer
this.customerEmail = customerEmail;
this.customerType = customerType;
}
-
+
}
diff --git a/src/main/java/com/programmers/springweekly/dto/voucher/request/VoucherCreateRequest.java b/src/main/java/com/programmers/springweekly/dto/voucher/request/VoucherCreateRequest.java
index 63b160cd2f..858f8a7f34 100644
--- a/src/main/java/com/programmers/springweekly/dto/voucher/request/VoucherCreateRequest.java
+++ b/src/main/java/com/programmers/springweekly/dto/voucher/request/VoucherCreateRequest.java
@@ -1,13 +1,18 @@
package com.programmers.springweekly.dto.voucher.request;
import com.programmers.springweekly.domain.voucher.VoucherType;
+import jakarta.validation.constraints.NotNull;
+import jakarta.validation.constraints.Positive;
import lombok.Builder;
import lombok.Getter;
@Getter
public class VoucherCreateRequest {
+ @Positive
private long discountAmount;
+
+ @NotNull
private VoucherType voucherType;
@Builder
@@ -15,5 +20,5 @@ public VoucherCreateRequest(long discountAmount, VoucherType voucherType) {
this.discountAmount = discountAmount;
this.voucherType = voucherType;
}
-
+
}
diff --git a/src/main/java/com/programmers/springweekly/exception/GlobalExceptionHandler.java b/src/main/java/com/programmers/springweekly/exception/GlobalExceptionHandler.java
new file mode 100644
index 0000000000..c6e5767ff5
--- /dev/null
+++ b/src/main/java/com/programmers/springweekly/exception/GlobalExceptionHandler.java
@@ -0,0 +1,99 @@
+package com.programmers.springweekly.exception;
+
+import java.util.NoSuchElementException;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.dao.DataAccessException;
+import org.springframework.dao.DuplicateKeyException;
+import org.springframework.http.HttpStatus;
+import org.springframework.ui.Model;
+import org.springframework.web.bind.MethodArgumentNotValidException;
+import org.springframework.web.bind.annotation.ControllerAdvice;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.ResponseStatus;
+
+@Slf4j
+@ControllerAdvice
+public class GlobalExceptionHandler {
+
+ private static final String ERROR_MSG = "errorMsg";
+ private static final String ERROR_CODE = "errorCode";
+ private static final String ERROR_PAGE = "errorPage";
+
+ @ExceptionHandler(MethodArgumentNotValidException.class)
+ @ResponseStatus(HttpStatus.BAD_REQUEST)
+ public String handleMethodArgumentNotValidException(MethodArgumentNotValidException e, Model model) {
+ log.warn("GlobalExceptionHandler - MethodArgumentNotValidException 발생, 데이터 검증 실패 {}", e.getMessage(), e);
+ addAttributeInModel(e.getBindingResult().getAllErrors().get(0).getDefaultMessage(), 400, model);
+
+ return ERROR_PAGE;
+ }
+
+ @ExceptionHandler(NoSuchElementException.class)
+ @ResponseStatus(HttpStatus.NOT_FOUND)
+ public String handleNoSuchElementException(NoSuchElementException e, Model model) {
+ log.warn("GlobalExceptionHandler - NoSuchElementException 발생, 찾는 데이터가 없음 {}", e.getMessage(), e);
+ addAttributeInModel(e.getMessage(), 404, model);
+
+ return ERROR_PAGE;
+ }
+
+ @ExceptionHandler(NullPointerException.class)
+ @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
+ public String handleNullPointerException(NullPointerException e, Model model) {
+ log.error("GlobalExceptionHandler - NullPointerException 발생 {}", e.getMessage(), e);
+ addAttributeInModel(e.getMessage(), 500, model);
+
+ return ERROR_PAGE;
+ }
+
+ @ExceptionHandler(IllegalArgumentException.class)
+ @ResponseStatus(HttpStatus.BAD_REQUEST)
+ public String handleIllegalArgumentException(IllegalArgumentException e, Model model) {
+ log.error("GlobalExceptionHandler - IllegalArgumentException 발생, 클라이언트의 잘못된 입력 값 예상 {}", e.getMessage(), e);
+ addAttributeInModel(e.getMessage(), 400, model);
+
+ return ERROR_PAGE;
+ }
+
+ @ExceptionHandler(IndexOutOfBoundsException.class)
+ @ResponseStatus(HttpStatus.BAD_REQUEST)
+ public String handleIndexOutOfBoundsException(IndexOutOfBoundsException e, Model model) {
+ log.error("GlobalExceptionHandler - IndexOutOfBoundsException 발생, 배열의 범위를 초과한 작업 예상 {}", e.getMessage(), e);
+ addAttributeInModel(e.getMessage(), 400, model);
+
+ return ERROR_PAGE;
+ }
+
+ @ExceptionHandler(DuplicateKeyException.class)
+ @ResponseStatus(HttpStatus.CONFLICT)
+ public String handleDuplicateKeyException(DuplicateKeyException e, Model model) {
+ log.error("GlobalExceptionHandler - DuplicateKeyException 발생, 유니크/중복 키 충돌 예상 {}", e.getMessage(), e);
+ addAttributeInModel(e.getMessage(), 409, model);
+
+ return ERROR_PAGE;
+ }
+
+ @ExceptionHandler(DataAccessException.class)
+ @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
+ public String handleDataAccessException(DataAccessException e, Model model) {
+ log.error("GlobalExceptionHandler - DataAccessException 발생, 데이터 접근 관련 예외 {}", e.getMessage(), e);
+ addAttributeInModel(e.getMessage(), 500, model);
+
+ return ERROR_PAGE;
+ }
+
+ @ExceptionHandler(Exception.class)
+ @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
+ public String handleException(Exception e, Model model) {
+ log.error("GlobalExceptionHandler - Exception 발생, 개발자가 잡지 못한 예외 {}", e.getMessage(), e);
+ addAttributeInModel(e.getMessage(), 500, model);
+
+ return ERROR_PAGE;
+ }
+
+ private void addAttributeInModel(String errorMessage, int errorCode, Model model) {
+ model.addAttribute(ERROR_MSG, errorMessage);
+ model.addAttribute(ERROR_CODE, errorCode);
+ }
+
+}
diff --git a/src/main/java/com/programmers/springweekly/service/VoucherService.java b/src/main/java/com/programmers/springweekly/service/VoucherService.java
index beb8257301..fe762d43b9 100644
--- a/src/main/java/com/programmers/springweekly/service/VoucherService.java
+++ b/src/main/java/com/programmers/springweekly/service/VoucherService.java
@@ -12,7 +12,6 @@
import java.util.UUID;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
-import org.springframework.util.CollectionUtils;
@Service
@RequiredArgsConstructor
@@ -36,7 +35,7 @@ public void update(VoucherUpdateRequest voucherUpdateRequest) {
voucherUpdateRequest.getVoucherType(),
voucherUpdateRequest.getDiscountAmount()
);
-
+
voucherRepository.update(voucher);
}
@@ -50,10 +49,6 @@ public VoucherResponse findById(UUID voucherId) {
public VoucherListResponse findAll() {
List voucherList = voucherRepository.findAll();
- if (CollectionUtils.isEmpty(voucherList)) {
- throw new NoSuchElementException("바우처가 저장되어 있지 않습니다.");
- }
-
return new VoucherListResponse(voucherList.stream().map(VoucherResponse::new).toList());
}
diff --git a/src/main/java/com/programmers/springweekly/util/validator/VoucherValidator.java b/src/main/java/com/programmers/springweekly/util/validator/VoucherValidator.java
index e8a53ddb2b..fa6806c807 100644
--- a/src/main/java/com/programmers/springweekly/util/validator/VoucherValidator.java
+++ b/src/main/java/com/programmers/springweekly/util/validator/VoucherValidator.java
@@ -1,8 +1,6 @@
package com.programmers.springweekly.util.validator;
import com.programmers.springweekly.domain.voucher.VoucherType;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@@ -11,19 +9,16 @@
@Slf4j
public final class VoucherValidator {
- private static final Pattern numberPattern = Pattern.compile("\\d+");
private static final int PERCENT_MAX = 100;
private static final int PERCENT_AND_FIXED_MIN = 0;
- public static void validateVoucher(VoucherType voucherType, String discountAmount) {
+ public static void validateVoucher(VoucherType voucherType, long discountAmount) {
switch (voucherType) {
case FIXED -> {
- validateNumber(discountAmount);
validateFixedRange(discountAmount);
}
case PERCENT -> {
- validateNumber(discountAmount);
validatePercentRange(discountAmount);
}
default -> {
@@ -33,28 +28,18 @@ public static void validateVoucher(VoucherType voucherType, String discountAmoun
}
}
- private static void validateNumber(String input) {
- Matcher match = numberPattern.matcher(input);
- if (!match.matches()) {
- log.warn("고객이 입력한 문자열 {} 이 숫자 형태가 아니어서 예외 발생", input);
- throw new IllegalArgumentException("Input : " + input + ", 입력하신 것은 숫자가 아닙니다.");
- }
- }
-
- private static void validateFixedRange(String inputFixed) {
- int fixed = Integer.parseInt(inputFixed);
+ private static void validateFixedRange(long inputFixed) {
- if (fixed < PERCENT_AND_FIXED_MIN) {
+ if (inputFixed < PERCENT_AND_FIXED_MIN) {
log.warn("고객이 입력한 고정 할인 금액 {} 이 음수여서 예외 발생", inputFixed);
throw new IllegalArgumentException("Input : " + inputFixed + ", 입력하신 숫자는 음수입니다. 양수를 입력해주세요.");
}
}
- private static void validatePercentRange(String inputPercent) {
- int percent = Integer.parseInt(inputPercent);
+ private static void validatePercentRange(long inputPercent) {
- if (percent > PERCENT_MAX || percent < PERCENT_AND_FIXED_MIN) {
+ if (inputPercent > PERCENT_MAX || inputPercent < PERCENT_AND_FIXED_MIN) {
log.warn("고객이 입력한 퍼센트 할인 {}% 가 퍼센트 범위를 벗어나서 예외 발생", inputPercent);
throw new IllegalArgumentException("Input : " + inputPercent + ", 입력하신 숫자는 퍼센트 범위를 벗어납니다.");
}
diff --git a/src/main/java/com/programmers/springweekly/view/Console.java b/src/main/java/com/programmers/springweekly/view/Console.java
index af4639bd4f..84c41a6423 100644
--- a/src/main/java/com/programmers/springweekly/view/Console.java
+++ b/src/main/java/com/programmers/springweekly/view/Console.java
@@ -38,7 +38,7 @@ public VoucherCreateRequest inputVoucherCreate(VoucherType voucherType) {
String inputDiscountAmount = SCANNER.nextLine();
log.info("사용자가 입력한 할인 양 : {}", inputDiscountAmount);
- VoucherValidator.validateVoucher(voucherType, inputDiscountAmount);
+ VoucherValidator.validateVoucher(voucherType, Long.parseLong(inputDiscountAmount));
return VoucherCreateRequest.builder()
.discountAmount(Long.parseLong(inputDiscountAmount))
@@ -54,7 +54,7 @@ public VoucherUpdateRequest inputVoucherUpdate(UUID voucherId) {
ParseValidator.validateVoucherUpdateLength(voucherInfo);
VoucherType voucherType = VoucherType.from(voucherInfo[1]);
- VoucherValidator.validateVoucher(voucherType, voucherInfo[0]);
+ VoucherValidator.validateVoucher(voucherType, Long.parseLong(voucherInfo[0]));
return VoucherUpdateRequest.builder()
.voucherId(voucherId)
diff --git a/src/main/resources/static/common.css b/src/main/resources/static/common.css
new file mode 100644
index 0000000000..2b183c70bd
--- /dev/null
+++ b/src/main/resources/static/common.css
@@ -0,0 +1,38 @@
+body {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ flex-direction: column;
+ width: 100%;
+ height: 100vh;
+ font-family: 'Noto Sans KR', sans-serif;
+}
+
+.header1, .header2, .header3 {
+ margin: 3px 0px;
+ font-weight: bold;
+}
+
+.header1 {
+ font-size: 24px;
+}
+
+.header2 {
+ font-size: 19px;
+}
+
+.header3 {
+ font-size: 22px;
+}
+
+form {
+ width: 400px;
+}
+
+.inputHeader {
+ font-weight: bold;
+ font-size: 14px;
+ width: 100%;
+ margin: 5px 0px;
+}
+
diff --git a/src/main/resources/static/error.png b/src/main/resources/static/error.png
new file mode 100644
index 0000000000..e10d2ce829
Binary files /dev/null and b/src/main/resources/static/error.png differ
diff --git a/src/main/resources/templates/customer/create.html b/src/main/resources/templates/customer/create.html
new file mode 100644
index 0000000000..c2fbe92857
--- /dev/null
+++ b/src/main/resources/templates/customer/create.html
@@ -0,0 +1,55 @@
+
+
+
+
+
+
+ Document
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/main/resources/templates/customer/find.html b/src/main/resources/templates/customer/find.html
new file mode 100644
index 0000000000..738cbf2e7c
--- /dev/null
+++ b/src/main/resources/templates/customer/find.html
@@ -0,0 +1,53 @@
+
+
+
+
+
+
+
+
+
+
+ Title
+
+
+
+
+
+
+
고객 ID
+
+
고객 이름
+
+
고객 이메일
+
+
고객 타입
+
+
+
+
diff --git a/src/main/resources/templates/customer/findAll.html b/src/main/resources/templates/customer/findAll.html
new file mode 100644
index 0000000000..b171f3f829
--- /dev/null
+++ b/src/main/resources/templates/customer/findAll.html
@@ -0,0 +1,75 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ Document
+
+
+
+
+
+
+
+ | 고객 ID |
+ 고객 이름 |
+ 고객 이메일 |
+ 고객 타입 |
+ 고객 정보 |
+ 고객 삭제 |
+
+
+
+
+ | 고객 ID |
+ 고객 이름 |
+ 고객 이메일 |
+ 고객 타입 |
+
+
+ |
+
+
+ |
+
+
+
+
+
+
+
diff --git a/src/main/resources/templates/customer/menu.html b/src/main/resources/templates/customer/menu.html
new file mode 100644
index 0000000000..d8b3cdd455
--- /dev/null
+++ b/src/main/resources/templates/customer/menu.html
@@ -0,0 +1,41 @@
+
+
+
+
+
+
+ Document
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/main/resources/templates/errorPage.html b/src/main/resources/templates/errorPage.html
new file mode 100644
index 0000000000..c047104ba1
--- /dev/null
+++ b/src/main/resources/templates/errorPage.html
@@ -0,0 +1,38 @@
+
+
+
+
+
+
+
+
+
+
+ Title
+
+
+
+에러 페이지
+
+

+
에러 코드
+
+
에러 메시지
+
+
+
+
diff --git a/src/main/resources/templates/home.html b/src/main/resources/templates/home.html
new file mode 100644
index 0000000000..ef4187a52c
--- /dev/null
+++ b/src/main/resources/templates/home.html
@@ -0,0 +1,31 @@
+
+
+
+
+
+
+ Document
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/main/resources/templates/voucher/create.html b/src/main/resources/templates/voucher/create.html
new file mode 100644
index 0000000000..507ad52c4d
--- /dev/null
+++ b/src/main/resources/templates/voucher/create.html
@@ -0,0 +1,49 @@
+
+
+
+
+
+
+ Document
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/main/resources/templates/voucher/find.html b/src/main/resources/templates/voucher/find.html
new file mode 100644
index 0000000000..d5fa2daa71
--- /dev/null
+++ b/src/main/resources/templates/voucher/find.html
@@ -0,0 +1,51 @@
+
+
+
+
+
+
+
+
+
+
+ Title
+
+
+
+
+
+
+
바우처 ID
+
+
바우처 타입
+
+
바우처 할인 양
+
+
+
+
diff --git a/src/main/resources/templates/voucher/findAll.html b/src/main/resources/templates/voucher/findAll.html
new file mode 100644
index 0000000000..6234bc3015
--- /dev/null
+++ b/src/main/resources/templates/voucher/findAll.html
@@ -0,0 +1,73 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ Document
+
+
+
+
+
+
+
+ | 바우처 ID |
+ 바우처 타입 |
+ 바우처 할인 양 |
+ 바우처 정보 |
+ 바우처 삭제 |
+
+
+
+
+ | 바우처 ID |
+ 바우처 타입 |
+ 바우처 할인 양 |
+
+
+ |
+
+
+ |
+
+
+
+
+
+
+
diff --git a/src/main/resources/templates/voucher/menu.html b/src/main/resources/templates/voucher/menu.html
new file mode 100644
index 0000000000..b23535849e
--- /dev/null
+++ b/src/main/resources/templates/voucher/menu.html
@@ -0,0 +1,41 @@
+
+
+
+
+
+
+ Document
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/test/java/com/programmers/springweekly/service/voucher/VoucherServiceTest.java b/src/test/java/com/programmers/springweekly/service/voucher/VoucherServiceTest.java
index 21706e0121..042be57ef5 100644
--- a/src/test/java/com/programmers/springweekly/service/voucher/VoucherServiceTest.java
+++ b/src/test/java/com/programmers/springweekly/service/voucher/VoucherServiceTest.java
@@ -117,8 +117,6 @@ void deleteAll() {
voucherService.deleteAll();
// then
- assertThatThrownBy(() -> voucherService.findAll())
- .isInstanceOf(NoSuchElementException.class)
- .hasMessage("바우처가 저장되어 있지 않습니다.");
+ assertThat(voucherService.findAll().getVoucherList().size()).isEqualTo(0);
}
}