diff --git "a/docs/2\354\243\274\354\260\250 \352\270\260\353\212\245\353\252\205\354\204\270\354\204\234.md" "b/docs/2\354\243\274\354\260\250 \352\270\260\353\212\245\353\252\205\354\204\270\354\204\234.md"
new file mode 100644
index 0000000000..b657033a6c
--- /dev/null
+++ "b/docs/2\354\243\274\354\260\250 \352\270\260\353\212\245\353\252\205\354\204\270\354\204\234.md"
@@ -0,0 +1,86 @@
+# 2주차 기능 명세서
+
+## [요구사항]
+
+---
+
+### 1.입력
+> CLI (Command linke inteface)한 환경에서 실행되도록 한다.
+
+[ 프로그램 실행 구문 ]
+```
+=== Manage Program ===
+Type customer to select customer menu.
+Type voucher to select customer menu.
+Type exit to exit the program.
+```
+
+[ voucher 실행 구문 ]
+```
+=== Voucher Manage ===
+Type exit to exit the program.
+Type create to create a new voucher.
+Type list to list all vouchers.
+```
+
+[ customer 실행 구문 ]
+```
+=== Customer Manage ===
+Type exit to exit the program.
+Type create to create a new customer.
+Type list to list all customers.
+```
+
+### 입력 예외 추가 기능
+- 입력시 `양쪽 공백`은 `삭제`
+- `대소문자 상관없이` 동일한 메뉴 이름이면 사용가능
+
+### 2. 회원
+> `create`와 `list` 커맨드를 통해 회원를 생성 및 조회할 수 있다.
+
+- `create`: 회원 생성
+- `list`: 회원 조회
+- customers 테이블 정의 및 추가
+ - CustomerRepository 추가 및 `JdbcTemplate`을 사용해서 구현
+ - CRUD 모든 기능 추가
+
+
+## 3. 바우처
+- `JdbcTemplate`을 사용해서 구현
+- CRUD 모든 기능 추가
+
+## 4. 바우처 지갑 (심화)
+- 특정 고객에게 바우처를 할당할 수 있습니다.
+- 고객이 어떤 바우처를 보유하고 있는지 조회할 수 있어야 합니다.
+- 고객이 보유한 바우처를 제거할 수 있어야 합니다.
+- 특정 바우처를 보유한 고객을 조회할 수 있어야 합니다.
+
+
+
+## 기능
+
+---
+
+### 1. 입력
+- [x] 회원과 바우처 선택하는 기능
+
+### 2. 바우처
+- [x] JdbcTemplate를 사용하여 Repostiroy 관리
+- [x] CRUD 기능
+
+### 3. 회원
+- [x] 회원 CRUD 기능
+ - [x] 회원 추가
+ - [x] 회원 삭제
+ - [x] 회원 업데이트
+ - [x] 회원 조회
+- [x] JdbcTemplate를 사용하여 Repository 관리
+
+### 4. 심화
+- [ ] 지갑 생성
+- [ ] 고객이 바우처 조회 기능
+- [ ] 고객이 보유한 바우처 제거 기능
+- [ ] 특정 바우처를 보유한 고객 조회 기능
+
+
+
diff --git a/docs/README.md b/docs/README.md
index 64979c406f..4d12d67ec3 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -34,7 +34,8 @@ Type list to list all vouchers.
- 파일을 읽을 수 있고 리스트 조회 가능
-### 3. 기타 요구사항
+
+### 기타 요구사항
- `YAML`프러퍼티를 만들고 어떤 설정을 만들 수 있을지
- 실행가능한 `jar`파일을 생성
- `logback`을 통한 에러 파일로 기록
diff --git a/pom.xml b/pom.xml
index eed0ea226d..72e5a7a170 100644
--- a/pom.xml
+++ b/pom.xml
@@ -28,8 +28,39 @@
spring-boot-starter-test
test
+
+
+ org.springframework.boot
+ spring-boot-starter-jdbc
+
+
+
+ mysql
+ mysql-connector-java
+ 8.0.28
+
+
+
+ org.testcontainers
+ testcontainers
+ 1.18.3
+ test
+
+
+ org.testcontainers
+ junit-jupiter
+ 1.18.3
+ test
+
+
+ org.testcontainers
+ mysql
+ 1.18.3
+ test
+
+
diff --git a/src/main/java/org/weekly/weekly/VoucherManageApplication.java b/src/main/java/org/weekly/weekly/VoucherManageApplication.java
index fad07c1435..7fe8ed5f34 100644
--- a/src/main/java/org/weekly/weekly/VoucherManageApplication.java
+++ b/src/main/java/org/weekly/weekly/VoucherManageApplication.java
@@ -3,14 +3,12 @@
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
-import org.weekly.weekly.voucher.controller.VoucherController;
@SpringBootApplication
public class VoucherManageApplication {
-
public static void main(String[] args) {
+
ApplicationContext context = SpringApplication.run(VoucherManageApplication.class, args);
- context.getBean(VoucherController.class).start();
+ context.getBean(VoucherManagementController.class).start();
}
-
}
\ No newline at end of file
diff --git a/src/main/java/org/weekly/weekly/VoucherManagementController.java b/src/main/java/org/weekly/weekly/VoucherManagementController.java
new file mode 100644
index 0000000000..8cc14adbd3
--- /dev/null
+++ b/src/main/java/org/weekly/weekly/VoucherManagementController.java
@@ -0,0 +1,164 @@
+package org.weekly.weekly;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+import org.weekly.weekly.customer.controller.CustomerController;
+import org.weekly.weekly.customer.dto.request.CustomerCreationRequest;
+import org.weekly.weekly.customer.dto.request.CustomerUpdateRequest;
+import org.weekly.weekly.customer.dto.response.CustomerResponse;
+import org.weekly.weekly.customer.dto.response.CustomersResponse;
+import org.weekly.weekly.ui.CommandLineApplication;
+import org.weekly.weekly.util.CustomerMenu;
+import org.weekly.weekly.util.ManageMenu;
+import org.weekly.weekly.util.PrintMessageType;
+import org.weekly.weekly.util.VoucherMenu;
+import org.weekly.weekly.voucher.controller.VoucherController;
+import org.weekly.weekly.voucher.dto.Response;
+import org.weekly.weekly.voucher.dto.request.VoucherCreationRequest;
+
+import java.util.List;
+
+@Component
+public class VoucherManagementController {
+ private final Logger logger = LoggerFactory.getLogger(VoucherManagementController.class);
+ private final CommandLineApplication commandLineApplication;
+ private final VoucherController voucherController;
+ private final CustomerController customerController;
+
+ public VoucherManagementController(CommandLineApplication commandLineApplication, VoucherController voucherController, CustomerController customerController) {
+ this.commandLineApplication = commandLineApplication;
+ this.voucherController = voucherController;
+ this.customerController = customerController;
+ }
+
+ public void start() {
+ boolean isExit = false;
+
+ while(!isExit) {
+ try {
+ ManageMenu manageMenu = commandLineApplication.readManageMenu();
+ isExit = processManageMenuSelection(manageMenu);
+ } catch (RuntimeException runtimeException) {
+ commandLineApplication.printErrorMsg(runtimeException.getMessage());
+ }
+ }
+ }
+
+ private boolean processManageMenuSelection(ManageMenu manageMenu) {
+ if (ManageMenu.EXIT.equals(manageMenu)) {
+ return true;
+ }
+
+ if (ManageMenu.VOUCHER.equals(manageMenu)) {
+ VoucherMenu voucherMenu = commandLineApplication.readVoucherMenu();
+ processVoucherMenuSelection(voucherMenu);
+ return false;
+ }
+
+ if (ManageMenu.CUSTOMER.equals(manageMenu)){
+ CustomerMenu customerMenu = commandLineApplication.readCustomerMenu();
+ processCustomerMenuSelection(customerMenu);
+ return false;
+ }
+
+ return true;
+ }
+
+ private boolean processVoucherMenuSelection(VoucherMenu selectMenu) {
+ if (VoucherMenu.CREATE.equals(selectMenu)) {
+ handleVoucherCreation();
+ return false;
+ }
+
+ if (VoucherMenu.LIST.equals(selectMenu)) {
+ handleVoucherSearch();
+ return false;
+ }
+
+
+ return true;
+ }
+
+ private void handleVoucherCreation() {
+ VoucherCreationRequest voucherCreationRequest = commandLineApplication.createVoucherFromInput();
+ Response response = voucherController.createVoucher(voucherCreationRequest);
+ logger.info("{}{}", PrintMessageType.CREATE_VOUCHER_SUCCESS.getMessage(),response.getResult());
+ commandLineApplication.printResult(response);
+ }
+
+ private void handleVoucherSearch() {
+ Response response = voucherController.getVouchers();
+ logger.info("{}{}", PrintMessageType.FIND_ALL_VOUCHER_SUCCESS.getMessage(), response.getResult());
+ commandLineApplication.printResult(response);
+ }
+
+ private boolean processCustomerMenuSelection(CustomerMenu selectMenu) {
+ if (CustomerMenu.CREATE.equals(selectMenu)) {
+ handleCustomerCreation();
+ return false;
+ }
+
+ if (CustomerMenu.DELETE.equals(selectMenu)) {
+ handleCustomerDelete();
+ return false;
+ }
+
+ if (CustomerMenu.DELETE_ALL.equals(selectMenu)) {
+ handleCustomerDeleteAll();
+ return false;
+ }
+
+ if (CustomerMenu.FIND_ALL.equals(selectMenu)) {
+ handleCustomerFindAll();
+ return false;
+ }
+
+ if (CustomerMenu.FIND_DETAIL.equals(selectMenu)) {
+ handleFindDetail();
+ return false;
+ }
+
+ if (CustomerMenu.UPDATE.equals(selectMenu)) {
+ handleUpdateCustomer();
+ return false;
+ }
+
+ return true;
+ }
+
+ private void handleCustomerCreation() {
+ CustomerCreationRequest customerCreation = commandLineApplication.createCustomerFromInput();
+ CustomerResponse customerDto = customerController.createCustomer(customerCreation);
+ commandLineApplication.printResult(customerDto);
+ }
+
+ private void handleCustomerDelete() {
+ CustomerUpdateRequest customerUpdateRequest = commandLineApplication.customerDetailFromInput();
+ customerController.deleteCustomer(customerUpdateRequest);
+ commandLineApplication.printDeleteMessage();
+ }
+
+ private void handleCustomerDeleteAll() {
+ customerController.deleteAllCustomer();
+ commandLineApplication.printDeleteMessage();
+ }
+
+ private void handleCustomerFindAll() {
+ CustomersResponse customerResponses = customerController.findAllCustomer();
+ commandLineApplication.printResult(customerResponses);
+ }
+
+ private void handleFindDetail() {
+ CustomerUpdateRequest customerUpdateRequest = commandLineApplication.customerDetailFromInput();
+ CustomerResponse customerResponse = customerController.findDetailCustomer(customerUpdateRequest);
+ commandLineApplication.printResult(customerResponse);
+ }
+
+ private void handleUpdateCustomer() {
+ CustomerUpdateRequest customerUpdateRequest = commandLineApplication.customerUpdateRequest();
+ CustomerResponse customerResponse = customerController.updateCustomer(customerUpdateRequest);
+ commandLineApplication.printResult(customerResponse);
+ }
+
+}
diff --git a/src/main/java/org/weekly/weekly/customer/controller/CustomerController.java b/src/main/java/org/weekly/weekly/customer/controller/CustomerController.java
new file mode 100644
index 0000000000..83abc90697
--- /dev/null
+++ b/src/main/java/org/weekly/weekly/customer/controller/CustomerController.java
@@ -0,0 +1,44 @@
+package org.weekly.weekly.customer.controller;
+
+import org.springframework.stereotype.Controller;
+import org.weekly.weekly.customer.dto.request.CustomerCreationRequest;
+import org.weekly.weekly.customer.dto.request.CustomerUpdateRequest;
+import org.weekly.weekly.customer.dto.response.CustomerResponse;
+import org.weekly.weekly.customer.dto.response.CustomersResponse;
+import org.weekly.weekly.customer.service.CustomerService;
+
+import java.util.List;
+
+@Controller
+public class CustomerController {
+
+ private final CustomerService customerService;
+
+ public CustomerController(CustomerService customerService) {
+ this.customerService = customerService;
+ }
+
+ public CustomerResponse createCustomer(CustomerCreationRequest creationRequest) {
+ return customerService.createCustomer(creationRequest);
+ }
+
+ public void deleteCustomer(CustomerUpdateRequest updateRequest) {
+ customerService.deleteCustomer(updateRequest);
+ }
+
+ public void deleteAllCustomer() {
+ customerService.deleteAllCustomers();
+ }
+
+ public CustomerResponse findDetailCustomer(CustomerUpdateRequest updateRequest) {
+ return customerService.findDetailCustomer(updateRequest);
+ }
+
+ public CustomersResponse findAllCustomer() {
+ return customerService.findAllCustomer();
+ }
+
+ public CustomerResponse updateCustomer(CustomerUpdateRequest updateRequest) {
+ return customerService.updateCustomer(updateRequest);
+ }
+}
diff --git a/src/main/java/org/weekly/weekly/customer/domain/Customer.java b/src/main/java/org/weekly/weekly/customer/domain/Customer.java
new file mode 100644
index 0000000000..b6cdb8d6fb
--- /dev/null
+++ b/src/main/java/org/weekly/weekly/customer/domain/Customer.java
@@ -0,0 +1,45 @@
+package org.weekly.weekly.customer.domain;
+
+import org.weekly.weekly.customer.exception.CustomerValidator;
+
+import java.time.LocalDateTime;
+import java.util.UUID;
+
+public class Customer {
+ UUID customerId;
+ String name;
+ String email;
+ LocalDateTime createAt;
+
+ public Customer(UUID customerId, String name, String email, LocalDateTime createAt) {
+ this.name = name;
+ this.email = email;
+ this.customerId = customerId;
+ this.createAt = createAt;
+ }
+
+ public static Customer of(UUID uuid, String name, String email) {
+ CustomerValidator.validateEmailFormat(email);
+ return new Customer(uuid, name, email, LocalDateTime.now());
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public LocalDateTime getCreateAt() {
+ return createAt;
+ }
+
+ public String getEmail() {
+ return email;
+ }
+
+ public UUID getCustomerId() {
+ return customerId;
+ }
+
+ public void updateEmail(String email) {
+ this.email = email;
+ }
+}
diff --git a/src/main/java/org/weekly/weekly/customer/dto/request/CustomerCreationRequest.java b/src/main/java/org/weekly/weekly/customer/dto/request/CustomerCreationRequest.java
new file mode 100644
index 0000000000..f21ac3cb5b
--- /dev/null
+++ b/src/main/java/org/weekly/weekly/customer/dto/request/CustomerCreationRequest.java
@@ -0,0 +1,30 @@
+package org.weekly.weekly.customer.dto.request;
+
+import org.weekly.weekly.customer.domain.Customer;
+import org.weekly.weekly.ui.exception.InputValidator;
+
+import java.util.UUID;
+
+public class CustomerCreationRequest {
+ private String email;
+ private String name;
+
+ public CustomerCreationRequest(String email, String name) {
+ this.email = email;
+ this.name = name;
+ }
+
+ public static CustomerCreationRequest of(String email, String name) {
+ InputValidator.isEmpty(email);
+ InputValidator.isEmpty(name);
+ return new CustomerCreationRequest(email, name);
+ }
+
+ public Customer toCustomer() {
+ return Customer.of(UUID.randomUUID(), name, email);
+ }
+
+ public String getEmail() {
+ return email;
+ }
+}
diff --git a/src/main/java/org/weekly/weekly/customer/dto/request/CustomerUpdateRequest.java b/src/main/java/org/weekly/weekly/customer/dto/request/CustomerUpdateRequest.java
new file mode 100644
index 0000000000..5567f226b4
--- /dev/null
+++ b/src/main/java/org/weekly/weekly/customer/dto/request/CustomerUpdateRequest.java
@@ -0,0 +1,33 @@
+package org.weekly.weekly.customer.dto.request;
+
+import org.weekly.weekly.ui.exception.InputValidator;
+
+public class CustomerUpdateRequest {
+ private String email;
+ private String newEmail;
+
+ private CustomerUpdateRequest(String email, String afterEmail) {
+ this.email = email;
+ this.newEmail = afterEmail;
+ }
+ private CustomerUpdateRequest(String email) {
+ this.email = email;
+ }
+
+ public static CustomerUpdateRequest of(String email) {
+ InputValidator.isEmpty(email);
+ return new CustomerUpdateRequest(email);
+ }
+
+ public static CustomerUpdateRequest of(String email, String afterEmail) {
+ InputValidator.isEmpty(email);
+ InputValidator.isEmpty(afterEmail);
+ return new CustomerUpdateRequest(email, afterEmail);
+ }
+
+ public String email() {
+ return email;
+ }
+
+ public String newEmail() {return newEmail;}
+}
diff --git a/src/main/java/org/weekly/weekly/customer/dto/response/CustomerResponse.java b/src/main/java/org/weekly/weekly/customer/dto/response/CustomerResponse.java
new file mode 100644
index 0000000000..343af5edb7
--- /dev/null
+++ b/src/main/java/org/weekly/weekly/customer/dto/response/CustomerResponse.java
@@ -0,0 +1,28 @@
+package org.weekly.weekly.customer.dto.response;
+
+import org.weekly.weekly.customer.domain.Customer;
+import org.weekly.weekly.voucher.dto.Response;
+
+import java.text.MessageFormat;
+import java.time.LocalDateTime;
+
+public class CustomerResponse implements Response {
+ String name;
+ String email;
+ LocalDateTime createAt;
+
+ private CustomerResponse(String name, String email, LocalDateTime createAt) {
+ this.name = name;
+ this.email = email;
+ this.createAt = createAt;
+ }
+
+ public static CustomerResponse of(Customer customer) {
+ return new CustomerResponse(customer.getName(), customer.getEmail(), customer.getCreateAt());
+ }
+
+ @Override
+ public String getResult() {
+ return MessageFormat.format("[이름: {0}, 이메일: {1}, 생성 시기: {2}]", name, email, createAt);
+ }
+}
diff --git a/src/main/java/org/weekly/weekly/customer/dto/response/CustomersResponse.java b/src/main/java/org/weekly/weekly/customer/dto/response/CustomersResponse.java
new file mode 100644
index 0000000000..eb601c9e82
--- /dev/null
+++ b/src/main/java/org/weekly/weekly/customer/dto/response/CustomersResponse.java
@@ -0,0 +1,31 @@
+package org.weekly.weekly.customer.dto.response;
+
+import org.weekly.weekly.customer.domain.Customer;
+import org.weekly.weekly.util.PrintMessageType;
+import org.weekly.weekly.voucher.domain.Voucher;
+import org.weekly.weekly.voucher.dto.Response;
+import org.weekly.weekly.voucher.dto.response.VoucherCreationResponse;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+public class CustomersResponse implements Response {
+ List result;
+
+ public CustomersResponse(List customers) {
+ result = customers.stream()
+ .map(CustomerResponse::of)
+ .collect(Collectors.toUnmodifiableList());
+ }
+
+ @Override
+ public String getResult() {
+ if (result.isEmpty()) {
+ return PrintMessageType.NO_VOUCHER_DATAS.getMessage();
+ }
+
+ StringBuilder resultBuilder = new StringBuilder();
+ result.forEach(customerResponse-> resultBuilder.append(customerResponse.getResult()).append('\n'));
+ return resultBuilder.toString();
+ }
+}
diff --git a/src/main/java/org/weekly/weekly/customer/exception/CustomerException.java b/src/main/java/org/weekly/weekly/customer/exception/CustomerException.java
new file mode 100644
index 0000000000..cfda9e7fa5
--- /dev/null
+++ b/src/main/java/org/weekly/weekly/customer/exception/CustomerException.java
@@ -0,0 +1,9 @@
+package org.weekly.weekly.customer.exception;
+
+import org.weekly.weekly.util.ExceptionMsg;
+
+public class CustomerException extends RuntimeException{
+ public CustomerException(ExceptionMsg exceptionMsg) {
+ super(exceptionMsg.getMsg());
+ }
+}
diff --git a/src/main/java/org/weekly/weekly/customer/exception/CustomerValidator.java b/src/main/java/org/weekly/weekly/customer/exception/CustomerValidator.java
new file mode 100644
index 0000000000..d30f721d32
--- /dev/null
+++ b/src/main/java/org/weekly/weekly/customer/exception/CustomerValidator.java
@@ -0,0 +1,18 @@
+package org.weekly.weekly.customer.exception;
+
+import org.weekly.weekly.util.ExceptionMsg;
+
+import java.util.regex.Pattern;
+
+public class CustomerValidator {
+
+ public CustomerValidator() {
+ throw new CustomerException(ExceptionMsg.UTIL_CLASS);
+ }
+ private static final String EMAIL_FORMAT = "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,3}$";
+ public static void validateEmailFormat(String email) {
+ if (!Pattern.matches(EMAIL_FORMAT, email)) {
+ throw new CustomerException(ExceptionMsg.NOT_EMAIL_FORMAT);
+ }
+ }
+}
diff --git a/src/main/java/org/weekly/weekly/customer/repository/CustomerRepository.java b/src/main/java/org/weekly/weekly/customer/repository/CustomerRepository.java
new file mode 100644
index 0000000000..a8a7352288
--- /dev/null
+++ b/src/main/java/org/weekly/weekly/customer/repository/CustomerRepository.java
@@ -0,0 +1,17 @@
+package org.weekly.weekly.customer.repository;
+
+import org.weekly.weekly.customer.domain.Customer;
+
+import java.util.List;
+import java.util.Optional;
+
+public interface CustomerRepository {
+ Customer insert(Customer customer);
+ void deleteByEmail(String email);
+ void deleteAll();
+ Optional findByEmail(String email);
+ List findAll();
+
+ Customer update(Customer customer, String newEmail);
+}
+
diff --git a/src/main/java/org/weekly/weekly/customer/repository/JdbcCustomerRepository.java b/src/main/java/org/weekly/weekly/customer/repository/JdbcCustomerRepository.java
new file mode 100644
index 0000000000..b332fa85f4
--- /dev/null
+++ b/src/main/java/org/weekly/weekly/customer/repository/JdbcCustomerRepository.java
@@ -0,0 +1,116 @@
+package org.weekly.weekly.customer.repository;
+
+import org.springframework.context.annotation.Profile;
+import org.springframework.dao.DataAccessException;
+import org.springframework.dao.EmptyResultDataAccessException;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.stereotype.Repository;
+import org.weekly.weekly.customer.domain.Customer;
+import org.weekly.weekly.customer.exception.CustomerException;
+import org.weekly.weekly.util.ExceptionMsg;
+import org.weekly.weekly.voucher.domain.DiscountType;
+import org.weekly.weekly.voucher.domain.Voucher;
+import org.weekly.weekly.voucher.exception.VoucherException;
+
+import javax.sql.DataSource;
+import java.nio.ByteBuffer;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Timestamp;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.util.List;
+import java.util.Optional;
+import java.util.UUID;
+
+@Profile("!dev")
+@Repository
+public class JdbcCustomerRepository implements CustomerRepository{
+ private final JdbcTemplate jdbcTemplate;
+
+ public JdbcCustomerRepository(DataSource dataSource) {
+ this.jdbcTemplate = new JdbcTemplate(dataSource);
+ }
+
+
+ @Override
+ public Customer insert(Customer customer) {
+ String sql = "INSERT INTO customers(customer_id, name, email, create_at) VALUES(UUID_TO_BIN(?), ?, ?, ?)";
+ int insert = jdbcTemplate.update(sql,
+ uuidToBytes(customer.getCustomerId()),
+ customer.getName(),
+ customer.getEmail(),
+ Timestamp.valueOf(customer.getCreateAt()));
+
+ if (insert != 1) {
+ throw new CustomerException(ExceptionMsg.SQL_INSERT_ERROR);
+ }
+ return customer;
+ }
+
+ @Override
+ public void deleteByEmail(String email) {
+ String sql = "DELETE FROM customers WHERE email = ?";
+ jdbcTemplate.update(sql, email);
+ }
+
+ @Override
+ public void deleteAll() {
+ String sql = "DELETE FROM customers";
+ jdbcTemplate.update(sql);
+ }
+
+ @Override
+ public Optional findByEmail(String email) {
+ String sql = "SELECT * FROM customers WHERE email = ?";
+
+ try {
+ return Optional.ofNullable(jdbcTemplate.queryForObject(sql, (rs, rowNum) -> mapToCustomer(rs), email));
+ } catch (EmptyResultDataAccessException exception) {
+ return Optional.empty();
+ }
+ }
+
+ @Override
+ public List findAll() {
+ String sql = "SELECT * FROM customers";
+ return jdbcTemplate.query(sql, (rs, rowNum) -> mapToCustomer(rs));
+ }
+
+ @Override
+ public Customer update(Customer customer, String newEmail) {
+ String sql = "UPDATE customers SET email = ? WHERE email = ?";
+
+ String beforeEmail = customer.getEmail();
+ customer.updateEmail(newEmail);
+
+ int update = jdbcTemplate.update(sql,
+ customer.getEmail(),
+ beforeEmail);
+
+ if (update != 1) {
+ throw new CustomerException(ExceptionMsg.SQL_ERROR);
+ }
+ return customer;
+ }
+
+
+ private static UUID toUUID(byte[] bytes) {
+ var buffer = ByteBuffer.wrap(bytes);
+ return new UUID(buffer.getLong(), buffer.getLong());
+ }
+
+ private Customer mapToCustomer(ResultSet resultSet) throws SQLException {
+ UUID customerId = toUUID(resultSet.getBytes("customer_id"));
+ String name = resultSet.getString("name");
+ String email = resultSet.getString("email");
+ LocalDateTime createAt = resultSet.getTimestamp("create_at") == null? null : resultSet.getTimestamp("create_at").toLocalDateTime();
+
+ return new Customer(customerId, name, email, createAt);
+ }
+
+
+ private byte[] uuidToBytes(UUID voucherId) {
+ return voucherId.toString().getBytes();
+ }
+}
diff --git a/src/main/java/org/weekly/weekly/customer/service/CustomerService.java b/src/main/java/org/weekly/weekly/customer/service/CustomerService.java
new file mode 100644
index 0000000000..dcfa849365
--- /dev/null
+++ b/src/main/java/org/weekly/weekly/customer/service/CustomerService.java
@@ -0,0 +1,80 @@
+package org.weekly.weekly.customer.service;
+
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.weekly.weekly.customer.domain.Customer;
+import org.weekly.weekly.customer.dto.request.CustomerCreationRequest;
+import org.weekly.weekly.customer.dto.request.CustomerUpdateRequest;
+import org.weekly.weekly.customer.dto.response.CustomerResponse;
+import org.weekly.weekly.customer.dto.response.CustomersResponse;
+import org.weekly.weekly.customer.exception.CustomerException;
+import org.weekly.weekly.customer.repository.CustomerRepository;
+import org.weekly.weekly.util.ExceptionMsg;
+
+import java.util.List;
+import java.util.Optional;
+
+@Service
+public class CustomerService {
+ private final CustomerRepository customerRepository;
+
+ public CustomerService(CustomerRepository customerRepository) {
+ this.customerRepository = customerRepository;
+ }
+
+ @Transactional
+ public CustomerResponse createCustomer(CustomerCreationRequest creationRequest) {
+ validateCustomerNotExist(creationRequest.getEmail());
+
+ Customer customer = creationRequest.toCustomer();
+ customerRepository.insert(customer);
+ return CustomerResponse.of(customer);
+ }
+
+ @Transactional
+ public void deleteCustomer(CustomerUpdateRequest updateRequest) {
+ String email = updateRequest.email();
+ customerRepository.deleteByEmail(email);
+ }
+
+ public void deleteAllCustomers() {
+ customerRepository.deleteAll();
+ }
+
+
+ public CustomerResponse findDetailCustomer(CustomerUpdateRequest updateRequest) {
+ String email = updateRequest.email();
+ Customer customer = validateCustomerExistAndGet(email);
+ return CustomerResponse.of(customer);
+ }
+
+ public CustomersResponse findAllCustomer() {
+ List customers = customerRepository.findAll();
+ return new CustomersResponse(customers);
+ }
+
+ @Transactional
+ public CustomerResponse updateCustomer(CustomerUpdateRequest updateRequest) {
+ validateCustomerNotExist(updateRequest.newEmail());
+
+ Customer customer = validateCustomerExistAndGet(updateRequest.email());
+
+ Customer updateCustomer = customerRepository.update(customer, updateRequest.newEmail());
+ return CustomerResponse.of(updateCustomer);
+ }
+
+ private void validateCustomerNotExist(String email) {
+ Optional findCustomer = customerRepository.findByEmail(email);
+ if (findCustomer.isPresent()) {
+ throw new CustomerException(ExceptionMsg.SQL_EXIST);
+ }
+ }
+
+ private Customer validateCustomerExistAndGet(String email) {
+ Optional customer = customerRepository.findByEmail(email);
+ if (customer.isEmpty()) {
+ throw new CustomerException(ExceptionMsg.SQL_ERROR);
+ }
+ return customer.get();
+ }
+}
diff --git a/src/main/java/org/weekly/weekly/ui/CommandLineApplication.java b/src/main/java/org/weekly/weekly/ui/CommandLineApplication.java
index 9ec07581dd..5798232ca1 100644
--- a/src/main/java/org/weekly/weekly/ui/CommandLineApplication.java
+++ b/src/main/java/org/weekly/weekly/ui/CommandLineApplication.java
@@ -2,46 +2,96 @@
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
+import org.weekly.weekly.customer.dto.request.CustomerCreationRequest;
+import org.weekly.weekly.customer.dto.request.CustomerUpdateRequest;
+import org.weekly.weekly.ui.exception.InputValidator;
import org.weekly.weekly.ui.reader.CommandReader;
-import org.weekly.weekly.ui.writer.CommandWriter;
-import org.weekly.weekly.util.DiscountType;
+import org.weekly.weekly.ui.writer.SystemWriter;
+import org.weekly.weekly.util.CustomerMenu;
+import org.weekly.weekly.util.ManageMenu;
+import org.weekly.weekly.util.Menu;
+import org.weekly.weekly.voucher.domain.DiscountType;
import org.weekly.weekly.util.VoucherMenu;
-import org.weekly.weekly.voucher.domain.Discount;
-import org.weekly.weekly.voucher.dto.VoucherDto;
import org.weekly.weekly.voucher.dto.Response;
-import org.weekly.weekly.voucher.dto.VoucherInfoRequest;
+import org.weekly.weekly.voucher.dto.request.VoucherInfoRequest;
+import org.weekly.weekly.voucher.dto.request.VoucherCreationRequest;
-import java.time.LocalDate;
-import java.util.UUID;
+import java.util.List;
+import java.util.function.Supplier;
@Component
public class CommandLineApplication {
private final CommandReader commandReader;
- private final CommandWriter commandWriter;
+ private final SystemWriter commandWriter;
@Autowired
- public CommandLineApplication(CommandReader commandReader, CommandWriter commandWriter) {
+ public CommandLineApplication(CommandReader commandReader, SystemWriter commandWriter) {
this.commandReader = commandReader;
this.commandWriter = commandWriter;
}
- public VoucherMenu readMenu() {
+ public ManageMenu readManageMenu() {
+ return readMenu(()-> {
+ commandWriter.printMangeProgram();
+ return ManageMenu.getMenu(readMenuInput());
+ });
+ }
+
+ public VoucherMenu readVoucherMenu() {
+ return readMenu(()-> {
+ commandWriter.printVoucherProgram();
+ return VoucherMenu.getMenu(readMenuInput());
+ });
+ }
+
+ public CustomerMenu readCustomerMenu() {
+ return readMenu(()-> {
+ commandWriter.printCustomerProgram();
+ return CustomerMenu.getMenu(readMenuInput());
+ });
+ }
+
+ public VoucherCreationRequest createVoucherFromInput() {
while(true) {
try {
- this.commandWriter.printVoucherProgram();
- return VoucherMenu.getMenu(this.commandReader.readLine());
+ DiscountType discountType = readDiscountType();
+ VoucherInfoRequest voucherInfoRequest = readVoucherInfo(discountType);
+ return new VoucherCreationRequest(voucherInfoRequest, discountType);
} catch (Exception exception) {
printErrorMsg(exception.getMessage());
}
}
}
- public VoucherDto readVoucher() {
+ public CustomerCreationRequest createCustomerFromInput() {
while(true) {
try {
- Discount discount = readDiscount();
- VoucherInfoRequest voucherInfoRequest = readVoucherInfo();
- return VoucherDto.parseDto(UUID.randomUUID(), voucherInfoRequest, discount, LocalDate.now());
+ String email = processEmail();
+ String name = processName();
+ return CustomerCreationRequest.of(email, name);
+ } catch (Exception exception) {
+ printErrorMsg(exception.getMessage());
+ }
+ }
+ }
+
+ public CustomerUpdateRequest customerDetailFromInput() {
+ while(true) {
+ try {
+ String email = processEmail();
+ return CustomerUpdateRequest.of(email);
+ } catch (Exception exception) {
+ printErrorMsg(exception.getMessage());
+ }
+ }
+ }
+
+ public CustomerUpdateRequest customerUpdateRequest(){
+ while(true) {
+ try {
+ String email = processEmail();
+ String newEmail = processNewEmail();
+ return CustomerUpdateRequest.of(email, newEmail);
} catch (Exception exception) {
printErrorMsg(exception.getMessage());
}
@@ -49,22 +99,64 @@ public VoucherDto readVoucher() {
}
public void printErrorMsg(String errorMsg) {
- this.commandWriter.printErrorMsg(errorMsg);
+ commandWriter.printErrorMessage(errorMsg);
}
public void printResult(Response response) {
- this.commandWriter.printReuslt(response.getResult());
+ commandWriter.printReuslt(response.getResult());
+ }
+
+ public void printDeleteMessage() {
+ commandWriter.printDeleteMessage();
+ }
+
+
+ private String readMenuInput() {
+ String userInput = commandReader.readLine();
+ InputValidator.isEmpty(userInput);
+ return userInput.toUpperCase();
+ }
+
+ private String readUserInput() {
+ String userInput = commandReader.readLine();
+ InputValidator.isEmpty(userInput);
+ return userInput;
+ }
+
+ private T readMenu(Supplier menuSupplier) {
+ while(true) {
+ try {
+ return menuSupplier.get();
+ } catch (Exception exception) {
+ printErrorMsg(exception.getMessage());
+ }
+ }
}
- private Discount readDiscount() throws Exception {
- this.commandWriter.printSelectDiscount();
- return DiscountType.getDiscountMap(this.commandReader.readLine()).getNewInstance();
+ private DiscountType readDiscountType() {
+ commandWriter.printSelectDiscount();
+ String no = readUserInput();
+ return DiscountType.getDiscountTypeByNumber(no);
}
- private VoucherInfoRequest readVoucherInfo() throws Exception {
- this.commandWriter.printCreateVoucher();
- return VoucherInfoRequest.of(this.commandReader.readLine());
+ private VoucherInfoRequest readVoucherInfo(DiscountType discountType){
+ commandWriter.printCreateVoucher(discountType);
+ String voucherInfo = readUserInput();
+ return VoucherInfoRequest.of(voucherInfo);
}
+ private String processEmail() {
+ commandWriter.printEmailInputMessage();
+ return readUserInput();
+ }
+ private String processNewEmail() {
+ commandWriter.printNewEmailInputMessage();
+ return readUserInput();
+ }
+
+ private String processName() {
+ commandWriter.printNameInputMessage();
+ return readUserInput();
+ }
}
diff --git a/src/main/java/org/weekly/weekly/ui/exception/InputException.java b/src/main/java/org/weekly/weekly/ui/exception/InputException.java
new file mode 100644
index 0000000000..6eb0516cfb
--- /dev/null
+++ b/src/main/java/org/weekly/weekly/ui/exception/InputException.java
@@ -0,0 +1,10 @@
+package org.weekly.weekly.ui.exception;
+
+import org.weekly.weekly.util.ExceptionMsg;
+
+public class InputException extends RuntimeException{
+
+ public InputException(ExceptionMsg exception) {
+ super(exception.getMsg());
+ }
+}
diff --git a/src/main/java/org/weekly/weekly/ui/exception/InputValidator.java b/src/main/java/org/weekly/weekly/ui/exception/InputValidator.java
new file mode 100644
index 0000000000..0c4c3ef6c0
--- /dev/null
+++ b/src/main/java/org/weekly/weekly/ui/exception/InputValidator.java
@@ -0,0 +1,34 @@
+package org.weekly.weekly.ui.exception;
+
+import org.weekly.weekly.util.ExceptionMsg;
+import org.weekly.weekly.voucher.exception.VoucherException;
+
+import java.util.Arrays;
+
+public class InputValidator {
+ public InputValidator() {
+ throw new InputException(ExceptionMsg.UTIL_CLASS);
+ }
+
+ private static final int VOUCHER_INPUT_SIZE = 2;
+ public static void isEmpty(String userInput) {
+ if (userInput == null || userInput.isBlank()) {
+ throw new RuntimeException(ExceptionMsg.EMPTY.getMsg());
+ }
+ }
+
+ public static void notVoucherInputSize(String[] userInputs) {
+ if (userInputs.length != VOUCHER_INPUT_SIZE) {
+ throw new InputException(ExceptionMsg.NOT_SAME_PARAM_SIZE);
+ }
+ }
+
+ public static void notNumber(String[] userInputs) {
+ try {
+ Arrays.stream(userInputs)
+ .peek(Long::parseLong);
+ } catch (NumberFormatException exception) {
+ throw new InputException(ExceptionMsg.NOT_INPUT_FORMAT);
+ }
+ }
+}
diff --git a/src/main/java/org/weekly/weekly/ui/exception/ReadException.java b/src/main/java/org/weekly/weekly/ui/exception/ReadException.java
deleted file mode 100644
index 9ea5e87e53..0000000000
--- a/src/main/java/org/weekly/weekly/ui/exception/ReadException.java
+++ /dev/null
@@ -1,31 +0,0 @@
-package org.weekly.weekly.ui.exception;
-
-import org.weekly.weekly.util.ExceptionMsg;
-
-import java.util.Arrays;
-
-public class ReadException {
-
- public static void isEmpty(String userInput) {
- if (userInput == null || userInput.isBlank()) {
- throw new RuntimeException(ExceptionMsg.EMPTY.getMsg());
- }
- }
-
- public static void notVoucherInputSize(String[] userInputs) {
- if (userInputs.length != 2) {
- throw new RuntimeException(ExceptionMsg.NOT_SAME_PARAM_SIZE.getMsg());
- }
- }
-
- public static void notVoucherInputFormat(String[] userInputs) {
- if (Arrays.stream(userInputs)
- .anyMatch(input -> isDigit(input.trim()))) {
- throw new RuntimeException(ExceptionMsg.NOT_INPUT_FORMAT.getMsg());
- }
- }
-
- private static boolean isDigit(String userInput) {
- return userInput.chars().anyMatch(value -> !Character.isDigit(value));
- }
-}
diff --git a/src/main/java/org/weekly/weekly/ui/reader/BufferedReaderWrap.java b/src/main/java/org/weekly/weekly/ui/reader/BufferedReaderWrap.java
index a904e8262b..6542b3dc7c 100644
--- a/src/main/java/org/weekly/weekly/ui/reader/BufferedReaderWrap.java
+++ b/src/main/java/org/weekly/weekly/ui/reader/BufferedReaderWrap.java
@@ -1,21 +1,29 @@
package org.weekly.weekly.ui.reader;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Component;
+import org.weekly.weekly.ui.exception.InputException;
+import org.weekly.weekly.util.ExceptionMsg;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
@Component
+@ConditionalOnProperty(value="command.read", havingValue = "buffer")
public class BufferedReaderWrap implements CommandReader {
private final BufferedReader bufferedReader;
public BufferedReaderWrap() {
- this.bufferedReader = new BufferedReader(new InputStreamReader(System.in));
+ bufferedReader = new BufferedReader(new InputStreamReader(System.in));
}
@Override
- public String readLine() throws IOException {
- return this.bufferedReader.readLine();
+ public String readLine(){
+ try {
+ return bufferedReader.readLine();
+ } catch (IOException exception) {
+ throw new InputException(ExceptionMsg.NOT_INPUT_FORMAT);
+ }
}
}
diff --git a/src/main/java/org/weekly/weekly/ui/reader/CommandReader.java b/src/main/java/org/weekly/weekly/ui/reader/CommandReader.java
index d9954851d3..9ba5cf6055 100644
--- a/src/main/java/org/weekly/weekly/ui/reader/CommandReader.java
+++ b/src/main/java/org/weekly/weekly/ui/reader/CommandReader.java
@@ -3,5 +3,5 @@
import java.io.IOException;
public interface CommandReader {
- String readLine() throws IOException;
+ String readLine();
}
diff --git a/src/main/java/org/weekly/weekly/ui/reader/ConsoleWrap.java b/src/main/java/org/weekly/weekly/ui/reader/ConsoleWrap.java
index a64197e61f..b4e02e6bb8 100644
--- a/src/main/java/org/weekly/weekly/ui/reader/ConsoleWrap.java
+++ b/src/main/java/org/weekly/weekly/ui/reader/ConsoleWrap.java
@@ -1,15 +1,17 @@
package org.weekly.weekly.ui.reader;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Component;
import java.io.Console;
@Component
+@ConditionalOnProperty(value="command.read", havingValue = "console")
public class ConsoleWrap implements CommandReader{
private final Console consoleWrap;
public ConsoleWrap() {
- this.consoleWrap = System.console();
+ consoleWrap = System.console();
}
@Override
diff --git a/src/main/java/org/weekly/weekly/ui/reader/ScannerWrap.java b/src/main/java/org/weekly/weekly/ui/reader/ScannerWrap.java
index a3629575ac..35fb98e407 100644
--- a/src/main/java/org/weekly/weekly/ui/reader/ScannerWrap.java
+++ b/src/main/java/org/weekly/weekly/ui/reader/ScannerWrap.java
@@ -1,28 +1,28 @@
package org.weekly.weekly.ui.reader;
-import org.springframework.context.annotation.Primary;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Component;
-import org.weekly.weekly.ui.exception.ReadException;
+import org.weekly.weekly.ui.exception.InputValidator;
import java.util.Scanner;
@Component
-@Primary
+@ConditionalOnProperty(value="command.read", havingValue = "scanner")
public class ScannerWrap implements CommandReader{
private final Scanner scanner;
public ScannerWrap() {
- this.scanner = new Scanner(System.in);
+ scanner = new Scanner(System.in);
}
@Override
public String readLine() {
- String userInput = this.scanner.nextLine().trim();
+ String userInput = scanner.nextLine().trim();
checkException(userInput);
- return userInput.toLowerCase();
+ return userInput;
}
private void checkException(String userInput) {
- ReadException.isEmpty(userInput);
+ InputValidator.isEmpty(userInput);
}
}
diff --git a/src/main/java/org/weekly/weekly/ui/writer/CommandWriter.java b/src/main/java/org/weekly/weekly/ui/writer/CommandWriter.java
index a31d25cfce..f26b91797c 100644
--- a/src/main/java/org/weekly/weekly/ui/writer/CommandWriter.java
+++ b/src/main/java/org/weekly/weekly/ui/writer/CommandWriter.java
@@ -1,49 +1,11 @@
package org.weekly.weekly.ui.writer;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.stereotype.Component;
-import org.weekly.weekly.util.DiscountType;
-import org.weekly.weekly.util.PrintMsg;
-import org.weekly.weekly.util.VoucherMenu;
-
-import java.util.Arrays;
-
-@Component
-public class CommandWriter {
- private final Logger logger = LoggerFactory.getLogger(CommandWriter.class);
- private void println(String msg) {
- System.out.println(msg);
- }
- private void print(String msg) {System.out.print(msg);}
-
- public void printVoucherProgram() {
- println(PrintMsg.EMPTY.getMsg());
- println(PrintMsg.PROGRAM.getMsg());
- Arrays.stream(VoucherMenu.values())
- .forEach(voucherMenu -> System.out.println(voucherMenu.getPrintMsg()));
- }
-
- public void printErrorMsg(String errorMsg) {
- logger.warn(errorMsg);
- println(PrintMsg.EMPTY.getMsg());
- println(errorMsg);
- }
-
- public void printCreateVoucher() {
- println(PrintMsg.EMPTY.getMsg());
- print(PrintMsg.CREATE_VOUCHER.getMsg());
- }
-
- public void printSelectDiscount() {
- println(PrintMsg.EMPTY.getMsg());
- println(PrintMsg.DISCOUNT_SELECT.getMsg());
- Arrays.stream(DiscountType.values())
- .forEach(discountMap -> System.out.println(discountMap.getMsg()));
- }
-
- public void printReuslt(String result) {
- println(PrintMsg.EMPTY.getMsg());
- println(result);
- }
+import org.weekly.weekly.voucher.domain.DiscountType;
+
+public interface CommandWriter {
+ void printVoucherProgram();
+ void printErrorMsg(String message);
+ void printCreateVoucher(DiscountType discountType);
+ void printSelectDiscount();
+ void printReuslt(String result);
}
diff --git a/src/main/java/org/weekly/weekly/ui/writer/SystemWriter.java b/src/main/java/org/weekly/weekly/ui/writer/SystemWriter.java
new file mode 100644
index 0000000000..241130f9f4
--- /dev/null
+++ b/src/main/java/org/weekly/weekly/ui/writer/SystemWriter.java
@@ -0,0 +1,80 @@
+package org.weekly.weekly.ui.writer;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.stereotype.Component;
+import org.weekly.weekly.util.*;
+import org.weekly.weekly.voucher.domain.DiscountType;
+
+import java.util.Arrays;
+
+@Component
+@ConditionalOnProperty(value="command.write", havingValue = "system")
+public class SystemWriter {
+ private final Logger logger = LoggerFactory.getLogger(SystemWriter.class);
+ private void println(String msg) {
+ System.out.println(msg);
+ }
+ private void print(String msg) {System.out.print(msg);}
+
+ public void printMangeProgram() {
+ printMenu(ManageMenu.values(), PrintMessageType.MANAGE_PROGRAM);
+ }
+
+ public void printVoucherProgram() {
+ printMenu(VoucherMenu.values(), PrintMessageType.VOUCHER_PROGRAM);
+ }
+
+ public void printCustomerProgram() {
+ printMenu(CustomerMenu.values(), PrintMessageType.CUSTOMER_PROGRAM);
+ }
+
+ public void printErrorMessage(String errorMsg) {
+ logger.warn(errorMsg);
+ println(PrintMessageType.EMPTY.getMessage());
+ println(errorMsg);
+ }
+
+ public void printCreateVoucher(DiscountType discountType) {
+ println(PrintMessageType.EMPTY.getMessage());
+ println(PrintMessageType.CREATE_VOUCHER.getMessage() + discountType.getInputExampleMessage());
+ print(PrintMessageType.INPUT_MESSAGE.getMessage());
+ }
+
+ public void printSelectDiscount() {
+ println(PrintMessageType.EMPTY.getMessage());
+ println(PrintMessageType.DISCOUNT_SELECT.getMessage());
+ Arrays.stream(DiscountType.values())
+ .forEach(discountMap -> System.out.println(discountMap.getSelectMessage()));
+ }
+
+ public void printEmailInputMessage() {
+ println(PrintMessageType.EMAIL_INPUT.getMessage());
+ }
+
+ public void printNewEmailInputMessage() {
+ println(PrintMessageType.NEW_EMAIL_INPUT.getMessage());
+ }
+
+ public void printNameInputMessage() {
+ println(PrintMessageType.NAME_INPUT.getMessage());
+ }
+
+ public void printReuslt(String result) {
+ println(PrintMessageType.EMPTY.getMessage());
+ println(result);
+ }
+
+ public void printDeleteMessage() {
+ println(PrintMessageType.DELETE.getMessage());
+ }
+
+
+ private void printMenu(Menu[] menus, PrintMessageType programMessage) {
+ println(PrintMessageType.EMPTY.getMessage());
+ println(programMessage.getMessage());
+ Arrays.stream(menus)
+ .forEach(menu -> System.out.println(menu.printMessage()));
+ }
+}
diff --git a/src/main/java/org/weekly/weekly/util/CustomerMenu.java b/src/main/java/org/weekly/weekly/util/CustomerMenu.java
new file mode 100644
index 0000000000..14bcd473fe
--- /dev/null
+++ b/src/main/java/org/weekly/weekly/util/CustomerMenu.java
@@ -0,0 +1,39 @@
+package org.weekly.weekly.util;
+
+import java.util.Arrays;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+public enum CustomerMenu implements Menu {
+ EXIT("[Type: exit] to exit the program."),
+ CREATE("[Type: create] to create a new voucher."),
+ DELETE("[Type: list] to list all vouchers."),
+ DELETE_ALL("[Type: delete_all] 모든 유저 삭제"),
+ FIND_ALL("[Type: find_all] 모든 유저 검색"),
+ FIND_DETAIL("[Type: find_detail] 유저 상세 검색"),
+ UPDATE("[Type: update] 유저 정보 업데이트");
+
+ private final String printMessage;
+ private static final Map CUSTOMER_MENU_MAP;
+ static {
+ CUSTOMER_MENU_MAP = new ConcurrentHashMap<>();
+ Arrays.stream(CustomerMenu.values())
+ .forEach(customerMenu -> CUSTOMER_MENU_MAP.put(customerMenu.name(), customerMenu));
+ }
+
+ CustomerMenu(String printMessage) {
+ this.printMessage = printMessage;
+ }
+
+ public static CustomerMenu getMenu(String userInput) {
+ if (CUSTOMER_MENU_MAP.containsKey(userInput)) {
+ return CUSTOMER_MENU_MAP.get(userInput);
+ }
+ throw new RuntimeException(ExceptionMsg.NOT_MENU.getMsg());
+ }
+
+ @Override
+ public String printMessage() {
+ return printMessage;
+ }
+}
diff --git a/src/main/java/org/weekly/weekly/util/DiscountType.java b/src/main/java/org/weekly/weekly/util/DiscountType.java
deleted file mode 100644
index 367a4aa851..0000000000
--- a/src/main/java/org/weekly/weekly/util/DiscountType.java
+++ /dev/null
@@ -1,53 +0,0 @@
-package org.weekly.weekly.util;
-
-import org.weekly.weekly.voucher.domain.Discount;
-import org.weekly.weekly.voucher.domain.FixedDiscount;
-import org.weekly.weekly.voucher.domain.PercentDiscount;
-
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
-
-public enum DiscountType {
- FIXED("1", FixedDiscount.class, "1. Fixed Discount"),
- PERCENT("2", PercentDiscount.class, "2. Percent Discount");
-
- private String no;
- private Class extends Discount> cls;
- private String msg;
-
- private static final Map discuontMap;
-
- static {
- Map map = new HashMap<>();
- for (DiscountType discount : DiscountType.values()) {
- map.put(discount.no, discount);
- }
- discuontMap = Collections.unmodifiableMap(map);
- }
-
- DiscountType(String no, Class extends Discount> cls, String msg) {
- this.no = no;
- this.cls = cls;
- this.msg = msg;
- }
-
- public static DiscountType getDiscountMap(String no) {
- if (discuontMap.containsKey(no)) {
- return discuontMap.get(no);
- }
- throw new RuntimeException(ExceptionMsg.NOT_DISCOUNT.getMsg());
- }
-
- public Discount getNewInstance() throws Exception {
- return this.cls.getDeclaredConstructor().newInstance();
- }
-
- public Class extends Discount> getCls() {
- return cls;
- }
-
- public String getMsg() {
- return msg;
- }
-}
diff --git a/src/main/java/org/weekly/weekly/util/ExceptionMsg.java b/src/main/java/org/weekly/weekly/util/ExceptionMsg.java
index 0bbbb47ea6..c77ec9ab02 100644
--- a/src/main/java/org/weekly/weekly/util/ExceptionMsg.java
+++ b/src/main/java/org/weekly/weekly/util/ExceptionMsg.java
@@ -2,6 +2,7 @@
public enum ExceptionMsg {
ERROR("[ERROR]: "),
+ UTIL_CLASS("유틸 클래스입니다."),
EMPTY("사용자가 아무 값도 입력하지 않았습니다."),
NOT_INPUT_FORMAT("입력 형식에 맞지 않습니다."),
NOT_MENU("해당 메뉴는 존재하지 않습니다."),
@@ -11,9 +12,14 @@ public enum ExceptionMsg {
EXPIRATION_ERROR("유효기간이 등록기간보다 빠릅니다."),
VOUCHER_EXIST("이미 존재하는 바우처입니다."),
NOT_FOUND("해당 종류의 할인정보를 찾을 수 없습니다."),
- NOT_SAME_PARAM_SIZE("입력 파라미터 개수가 맞지 않습니다.");
+ NOT_SAME_PARAM_SIZE("입력 파라미터 개수가 맞지 않습니다."),
+ NOT_EMAIL_FORMAT("이메일형식이 아닙니다."),
+ SQL_ERROR("값을 가져오기 실패"),
+ SQL_INSERT_ERROR("값 추가 실패"),
+ SQL_EXIST("이미 존재합니다."),
+ SQL_DELETE_ERROR("삭제 실패");
- private String msg;
+ private final String msg;
ExceptionMsg(String msg) {
this.msg = msg;
diff --git a/src/main/java/org/weekly/weekly/util/ManageMenu.java b/src/main/java/org/weekly/weekly/util/ManageMenu.java
new file mode 100644
index 0000000000..fcd829a672
--- /dev/null
+++ b/src/main/java/org/weekly/weekly/util/ManageMenu.java
@@ -0,0 +1,36 @@
+package org.weekly.weekly.util;
+
+import java.util.Arrays;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+public enum ManageMenu implements Menu {
+ EXIT("Type exit to exit the program."),
+ VOUCHER("Type voucher to voucher a new voucher."),
+ CUSTOMER("Type customer to customer all vouchers.");
+
+ private final String printMessage;
+ private static final Map MANAGE_MENU_MAP;
+
+ static {
+ MANAGE_MENU_MAP = new ConcurrentHashMap<>();
+ Arrays.stream(ManageMenu.values())
+ .forEach(manageMenu -> MANAGE_MENU_MAP.put(manageMenu.name(), manageMenu));
+ }
+
+ ManageMenu(String printMessage) {
+ this.printMessage = printMessage;
+ }
+
+ public static ManageMenu getMenu(String userInput) {
+ if (MANAGE_MENU_MAP.containsKey(userInput)) {
+ return MANAGE_MENU_MAP.get(userInput);
+ }
+ throw new RuntimeException(ExceptionMsg.NOT_MENU.getMsg());
+ }
+
+ @Override
+ public String printMessage() {
+ return printMessage;
+ }
+}
diff --git a/src/main/java/org/weekly/weekly/util/Menu.java b/src/main/java/org/weekly/weekly/util/Menu.java
new file mode 100644
index 0000000000..40981c0f93
--- /dev/null
+++ b/src/main/java/org/weekly/weekly/util/Menu.java
@@ -0,0 +1,5 @@
+package org.weekly.weekly.util;
+
+public interface Menu {
+ String printMessage();
+}
diff --git a/src/main/java/org/weekly/weekly/util/PrintMessageType.java b/src/main/java/org/weekly/weekly/util/PrintMessageType.java
new file mode 100644
index 0000000000..c42e69ef39
--- /dev/null
+++ b/src/main/java/org/weekly/weekly/util/PrintMessageType.java
@@ -0,0 +1,29 @@
+package org.weekly.weekly.util;
+
+public enum PrintMessageType {
+ MANAGE_PROGRAM("=== Manage Program ==="),
+ VOUCHER_PROGRAM("=== Voucher Program ==="),
+ CUSTOMER_PROGRAM("=== Customer Program ==="),
+ CREATE_VOUCHER("바우처를 생성합니다.\n" +
+ "입력예시 => "),
+ INPUT_MESSAGE("입력하세요: "),
+ DISCOUNT_SELECT("할인 종류중 하나를 선택하세요"),
+ EMAIL_INPUT("이메일을 입력하세요: "),
+ NEW_EMAIL_INPUT("새 이메일을 입력하세요: "),
+ NAME_INPUT("이름을 입력하세요"),
+ NO_VOUCHER_DATAS("저장소에 데이터가 없습니다."),
+ EMPTY(""),
+ CREATE_VOUCHER_SUCCESS("[바우처 생성에 성공]: "),
+ FIND_ALL_VOUCHER_SUCCESS("[모든 바우처 조회 성공]: "),
+ DELETE("삭제에 성공했습니다!");
+
+ private final String message;
+
+ PrintMessageType(String msg) {
+ this.message = msg;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+}
diff --git a/src/main/java/org/weekly/weekly/util/PrintMsg.java b/src/main/java/org/weekly/weekly/util/PrintMsg.java
deleted file mode 100644
index a89c6bbbae..0000000000
--- a/src/main/java/org/weekly/weekly/util/PrintMsg.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package org.weekly.weekly.util;
-
-public enum PrintMsg {
- PROGRAM("=== Voucher Program ==="),
- CREATE_VOUCHER("바우처를 생성합니다.\n" +
- "입력 예시\n" +
- " 1. 고정: 바우처 할인 금액,바우처 유효 개월 수\n" +
- " 2. 퍼센트: 바우처 퍼센트(0~100으로만), 바우처 유효 개월 수\n" +
- "(,)콤마를 기준으로 입력하세요 :"),
- DISCOUNT_SELECT("할인 종류중 하나를 선택하세요"),
- NO_VOUCHER_DATAS("저장소에 데이터가 없습니다."),
- EMPTY(""),
- CREATE_VOUCHER_SUCCESS("[바우처 생성에 성공]: "),
- FIND_ALL_VOUCHER_SUCCESS("[모든 바우처 조회 성공]: ");
-
- private String msg;
-
- PrintMsg(String msg) {
- this.msg = msg;
- }
-
- public String getMsg() {
- return msg;
- }
-}
diff --git a/src/main/java/org/weekly/weekly/util/VoucherMenu.java b/src/main/java/org/weekly/weekly/util/VoucherMenu.java
index c5da7f8eb0..a9b4e621ce 100644
--- a/src/main/java/org/weekly/weekly/util/VoucherMenu.java
+++ b/src/main/java/org/weekly/weekly/util/VoucherMenu.java
@@ -1,28 +1,24 @@
package org.weekly.weekly.util;
import java.util.Arrays;
-import java.util.Collections;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
-public enum VoucherMenu {
- EXIT("exit", "Type exit to exit the program."),
- CREATE("create", "Type create to create a new voucher."),
- LIST("list", "Type list to list all vouchers.");
-
- private String input;
- private String printMsg;
+public enum VoucherMenu implements Menu {
+ EXIT("Type exit to exit the program."),
+ CREATE("Type create to create a new voucher."),
+ LIST("Type list to list all vouchers.");
+ private final String printMessage;
private final static Map VOUCHER_MENU_MAP;
static {
VOUCHER_MENU_MAP = new ConcurrentHashMap<>();
Arrays.stream(VoucherMenu.values())
- .forEach(menu -> VOUCHER_MENU_MAP.put(menu.input, menu));
+ .forEach(menu -> VOUCHER_MENU_MAP.put(menu.name(), menu));
}
- VoucherMenu(String input, String printMsg) {
- this.input = input;
- this.printMsg = printMsg;
+ VoucherMenu(String printMsg) {
+ this.printMessage = printMsg;
}
public static VoucherMenu getMenu(String userInput) {
@@ -32,7 +28,8 @@ public static VoucherMenu getMenu(String userInput) {
throw new RuntimeException(ExceptionMsg.NOT_MENU.getMsg());
}
- public String getPrintMsg() {
- return printMsg;
+ @Override
+ public String printMessage() {
+ return printMessage;
}
}
\ No newline at end of file
diff --git a/src/main/java/org/weekly/weekly/voucher/controller/VoucherController.java b/src/main/java/org/weekly/weekly/voucher/controller/VoucherController.java
index f1c148a667..5e9c1e2804 100644
--- a/src/main/java/org/weekly/weekly/voucher/controller/VoucherController.java
+++ b/src/main/java/org/weekly/weekly/voucher/controller/VoucherController.java
@@ -3,60 +3,26 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
-import org.weekly.weekly.ui.CommandLineApplication;
-import org.weekly.weekly.util.PrintMsg;
-import org.weekly.weekly.util.VoucherMenu;
-import org.weekly.weekly.voucher.dto.VoucherDto;
import org.weekly.weekly.voucher.dto.Response;
+import org.weekly.weekly.voucher.dto.request.VoucherCreationRequest;
import org.weekly.weekly.voucher.service.VoucherService;
@Controller
public class VoucherController {
private final Logger logger = LoggerFactory.getLogger(VoucherController.class);
private final VoucherService voucherService;
- private final CommandLineApplication commandLineApplication;
- public VoucherController(VoucherService voucherService, CommandLineApplication commandLineApplication) {
- this.voucherService = voucherService;
- this.commandLineApplication = commandLineApplication;
- }
- public void start() {
- boolean isStop = false;
-
- while(!isStop) {
- try {
- isStop = selectMenu(this.commandLineApplication.readMenu());
- } catch (RuntimeException runtimeException) {
- this.commandLineApplication.printErrorMsg(runtimeException.getMessage());
- }
- }
+ public VoucherController(VoucherService voucherService) {
+ this.voucherService = voucherService;
}
- private boolean selectMenu(VoucherMenu voucherMenu) {
- if (VoucherMenu.CREATE.equals(voucherMenu)) {
- createVoucher();
- return false;
- }
-
- if (VoucherMenu.LIST.equals(voucherMenu)) {
- getList();
- return false;
- }
-
- return true;
- }
- private void createVoucher() {
- VoucherDto voucherDto = this.commandLineApplication.readVoucher();
- Response response = this.voucherService.insertVoucher(voucherDto);
- logger.info("{}{}",PrintMsg.CREATE_VOUCHER_SUCCESS.getMsg(),response.getResult());
- this.commandLineApplication.printResult(response);
+ public Response createVoucher(VoucherCreationRequest voucherCreationRequest) {
+ return voucherService.insertVoucher(voucherCreationRequest);
}
- private void getList() {
- Response response = this.voucherService.getVouchers();
- logger.info("{}{}",PrintMsg.FIND_ALL_VOUCHER_SUCCESS.getMsg());
- this.commandLineApplication.printResult(response);
+ public Response getVouchers() {
+ return voucherService.getVouchers();
}
}
diff --git a/src/main/java/org/weekly/weekly/voucher/domain/Discount.java b/src/main/java/org/weekly/weekly/voucher/domain/Discount.java
index d823a44342..c7dc3708a2 100644
--- a/src/main/java/org/weekly/weekly/voucher/domain/Discount.java
+++ b/src/main/java/org/weekly/weekly/voucher/domain/Discount.java
@@ -1,7 +1,5 @@
package org.weekly.weekly.voucher.domain;
-import org.weekly.weekly.util.DiscountType;
-
public interface Discount {
long applyDiscount(long beforeAmount, long discountAmount);
DiscountType discountType();
diff --git a/src/main/java/org/weekly/weekly/voucher/domain/DiscountType.java b/src/main/java/org/weekly/weekly/voucher/domain/DiscountType.java
new file mode 100644
index 0000000000..d27a2b602f
--- /dev/null
+++ b/src/main/java/org/weekly/weekly/voucher/domain/DiscountType.java
@@ -0,0 +1,70 @@
+package org.weekly.weekly.voucher.domain;
+
+import org.weekly.weekly.util.ExceptionMsg;
+import org.weekly.weekly.voucher.exception.VoucherException;
+
+import java.lang.reflect.InvocationTargetException;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+public enum DiscountType {
+ FIXED("1", FixedDiscount.class, "1. Fixed Discount", "바우처 할인 금액, 바우처 유효 개월 수"),
+ PERCENT("2", PercentDiscount.class, "2. Percent Discount", "0~100사이의 바우처 할인율, 바우처 유효 개월 수");
+
+ private final String no;
+ private final Class extends Discount> cls;
+ private final String selectMessage;
+ private final String inputExampleMessage;
+
+ private static final Map discuontTypeMap;
+
+ static {
+ Map map = new HashMap<>();
+ for (DiscountType discount : DiscountType.values()) {
+ map.put(discount.no, discount);
+ }
+ discuontTypeMap = Collections.unmodifiableMap(map);
+ }
+
+ DiscountType(String no, Class extends Discount> cls, String msg, String exMessage) {
+ this.no = no;
+ this.cls = cls;
+ this.selectMessage = msg;
+ this.inputExampleMessage = exMessage;
+ }
+
+ public static DiscountType getDiscountTypeByNumber(String no) {
+ if (discuontTypeMap.containsKey(no)) {
+ return discuontTypeMap.get(no);
+ }
+ throw new VoucherException(ExceptionMsg.NOT_DISCOUNT);
+ }
+
+ public static DiscountType getDiscountTypeByName(String name) {
+ for (DiscountType discount : DiscountType.values()) {
+ if (name.equals(discount.name())) {
+ return discount;
+ }
+ }
+ throw new VoucherException(ExceptionMsg.NOT_DISCOUNT);
+ }
+
+ public Discount getNewInstance() {
+ try {
+ return this.cls.getDeclaredConstructor().newInstance();
+ } catch (NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException exception) {
+ throw new VoucherException(ExceptionMsg.NOT_FOUND);
+ }
+
+ }
+
+
+ public String getSelectMessage() {
+ return selectMessage;
+ }
+
+ public String getInputExampleMessage() {
+ return inputExampleMessage;
+ }
+}
diff --git a/src/main/java/org/weekly/weekly/voucher/domain/FixedDiscount.java b/src/main/java/org/weekly/weekly/voucher/domain/FixedDiscount.java
index 9dcf21e072..b8621eb46f 100644
--- a/src/main/java/org/weekly/weekly/voucher/domain/FixedDiscount.java
+++ b/src/main/java/org/weekly/weekly/voucher/domain/FixedDiscount.java
@@ -1,7 +1,5 @@
package org.weekly.weekly.voucher.domain;
-import org.weekly.weekly.util.DiscountType;
-
public class FixedDiscount implements Discount{
@Override
public long applyDiscount(long beforeAmount, long discountAmount) {
diff --git a/src/main/java/org/weekly/weekly/voucher/domain/PercentDiscount.java b/src/main/java/org/weekly/weekly/voucher/domain/PercentDiscount.java
index d368157df3..8670ab08ca 100644
--- a/src/main/java/org/weekly/weekly/voucher/domain/PercentDiscount.java
+++ b/src/main/java/org/weekly/weekly/voucher/domain/PercentDiscount.java
@@ -1,7 +1,5 @@
package org.weekly.weekly.voucher.domain;
-import org.weekly.weekly.util.DiscountType;
-
public class PercentDiscount implements Discount{
private final int PERCENT = 100;
@Override
diff --git a/src/main/java/org/weekly/weekly/voucher/domain/Voucher.java b/src/main/java/org/weekly/weekly/voucher/domain/Voucher.java
index 22be047c67..f5242f721f 100644
--- a/src/main/java/org/weekly/weekly/voucher/domain/Voucher.java
+++ b/src/main/java/org/weekly/weekly/voucher/domain/Voucher.java
@@ -1,5 +1,9 @@
package org.weekly.weekly.voucher.domain;
+import org.weekly.weekly.util.ExceptionMsg;
+import org.weekly.weekly.voucher.exception.VoucherException;
+import org.weekly.weekly.voucher.exception.VoucherValidator;
+
import java.text.MessageFormat;
import java.time.LocalDate;
import java.util.UUID;
@@ -15,6 +19,7 @@ public class Voucher {
private Discount discount;
+
public Voucher(UUID voucherId, long amount, LocalDate registrationDate, LocalDate expirationDate, Discount discount) {
this.voucherId = voucherId;
this.amount = amount;
@@ -23,8 +28,14 @@ public Voucher(UUID voucherId, long amount, LocalDate registrationDate, LocalDat
this.discount = discount;
}
- public UUID getVoucherId() {
- return voucherId;
+ public static Voucher of(UUID id, long amount, LocalDate now, long expiration, DiscountType discountType) {
+ validation(now, expiration, discountType, amount);
+ return new Voucher(id, amount, now, now.plusMonths(expiration), discountType.getNewInstance());
+ }
+
+ private static void validation(LocalDate registrationDate, long expiration, DiscountType discountType, long amount) {
+ VoucherValidator.validateExpiration(registrationDate, expiration);
+ VoucherValidator.validateAmount(discountType, amount);
}
public long applyDiscount(long beforeAmount) {
@@ -34,12 +45,27 @@ public long applyDiscount(long beforeAmount) {
return afterAmount;
}
- this.amount -= afterAmount;
+ this.amount += afterAmount;
return 0L;
}
- @Override
- public String toString() {
- return MessageFormat.format("[ID: {0}, 금액: {1}, 등록일자: {2}, 유효기간: {3}]", voucherId,amount, registrationDate, expirationDate);
+ public UUID getVoucherId() {
+ return voucherId;
+ }
+
+ public LocalDate getExpirationDate() {
+ return expirationDate;
+ }
+
+ public LocalDate getRegistrationDate() {
+ return registrationDate;
+ }
+
+ public long getAmount() {
+ return amount;
+ }
+
+ public DiscountType getDiscountType() {
+ return discount.discountType();
}
}
diff --git a/src/main/java/org/weekly/weekly/voucher/dto/CreateResponse.java b/src/main/java/org/weekly/weekly/voucher/dto/CreateResponse.java
deleted file mode 100644
index e845075c8f..0000000000
--- a/src/main/java/org/weekly/weekly/voucher/dto/CreateResponse.java
+++ /dev/null
@@ -1,16 +0,0 @@
-package org.weekly.weekly.voucher.dto;
-
-import org.weekly.weekly.voucher.domain.Voucher;
-
-public class CreateResponse implements Response{
- private final String result;
-
- public CreateResponse(Voucher voucher) {
- this.result = voucher.toString();
- }
-
- @Override
- public String getResult() {
- return result;
- }
-}
diff --git a/src/main/java/org/weekly/weekly/voucher/dto/ListResponse.java b/src/main/java/org/weekly/weekly/voucher/dto/ListResponse.java
deleted file mode 100644
index b2a5f08aff..0000000000
--- a/src/main/java/org/weekly/weekly/voucher/dto/ListResponse.java
+++ /dev/null
@@ -1,27 +0,0 @@
-package org.weekly.weekly.voucher.dto;
-
-import org.weekly.weekly.util.PrintMsg;
-import org.weekly.weekly.voucher.domain.Voucher;
-
-import java.util.List;
-import java.util.stream.Collectors;
-
-public class ListResponse implements Response{
- private final List result;
-
- public ListResponse(List vouchers) {
- this.result = vouchers.stream()
- .map(Voucher::toString)
- .collect(Collectors.toUnmodifiableList());
- }
-
- public String getResult() {
- if (result.isEmpty()) {
- return PrintMsg.NO_VOUCHER_DATAS.getMsg();
- }
-
- StringBuilder sb = new StringBuilder();
- result.forEach(sb::append);
- return sb.toString();
- }
-}
diff --git a/src/main/java/org/weekly/weekly/voucher/dto/Response.java b/src/main/java/org/weekly/weekly/voucher/dto/Response.java
index 163a86e2be..86c2795d86 100644
--- a/src/main/java/org/weekly/weekly/voucher/dto/Response.java
+++ b/src/main/java/org/weekly/weekly/voucher/dto/Response.java
@@ -1,5 +1,8 @@
package org.weekly.weekly.voucher.dto;
-public interface Response {
+/**
+ * 모든 반환 값에 대해 동일한 동작을 적용시키고 싶어서 이렇게 했습니다.
+ */
+public interface Response {
String getResult();
}
diff --git a/src/main/java/org/weekly/weekly/voucher/dto/VoucherDto.java b/src/main/java/org/weekly/weekly/voucher/dto/VoucherDto.java
deleted file mode 100644
index 1b12a70f30..0000000000
--- a/src/main/java/org/weekly/weekly/voucher/dto/VoucherDto.java
+++ /dev/null
@@ -1,57 +0,0 @@
-package org.weekly.weekly.voucher.dto;
-
-import org.weekly.weekly.util.DiscountType;
-import org.weekly.weekly.voucher.domain.Discount;
-import org.weekly.weekly.voucher.domain.Voucher;
-import org.weekly.weekly.voucher.exception.VoucherException;
-
-import java.time.LocalDate;
-import java.util.UUID;
-
-public class VoucherDto {
- private static final int RANGE_START = 0;
- private static final int RANGE_END = 100;
-
- private final UUID voucherId;
- private final long amount;
- private final LocalDate registrationDate;
- private final LocalDate expirationDate;
- private final Discount discount;
-
- private VoucherDto(UUID voucherId, long amount, LocalDate registrationDate, LocalDate expirationDate, Discount discount) {
- this.voucherId = voucherId;
- this.amount = amount;
- this.registrationDate = registrationDate;
- this.expirationDate = expirationDate;
- this.discount = discount;
- }
-
- public static VoucherDto parseDto(UUID voucherId, VoucherInfoRequest voucherInfoRequest, Discount discount, LocalDate registrationDate) {
- checkException(voucherInfoRequest, registrationDate, discount);
- return new VoucherDto(voucherId
- , Long.parseLong(voucherInfoRequest.getAmount())
- , registrationDate
- , registrationDate.plusMonths(Long.parseLong(voucherInfoRequest.getExpiration()))
- , discount);
- }
-
- private static void checkException(VoucherInfoRequest voucherInfoRequest, LocalDate registrationDate, Discount discount) {
- VoucherException.expirationError(registrationDate, voucherInfoRequest.getExpiration());
- VoucherException.notNumberFormat(voucherInfoRequest.getExpiration(), input -> Long.parseLong(input) <= RANGE_START);
-
- if (discount.getClass().equals(DiscountType.PERCENT.getCls())) {
- VoucherException.notNumberFormat(voucherInfoRequest.getAmount(), input -> Long.parseLong(input) < RANGE_START || Long.parseLong(input) > RANGE_END);
- return;
- }
- VoucherException.notNumberFormat(voucherInfoRequest.getAmount(), input -> Long.parseLong(input) < RANGE_START);
-
- }
-
- public Voucher parseToVoucher() {
- return new Voucher(this.voucherId, this.amount, this.registrationDate, this.expirationDate, this.discount);
- }
-
- public UUID getVoucherId() {
- return voucherId;
- }
-}
\ No newline at end of file
diff --git a/src/main/java/org/weekly/weekly/voucher/dto/request/VoucherCreationRequest.java b/src/main/java/org/weekly/weekly/voucher/dto/request/VoucherCreationRequest.java
new file mode 100644
index 0000000000..76c137ed6e
--- /dev/null
+++ b/src/main/java/org/weekly/weekly/voucher/dto/request/VoucherCreationRequest.java
@@ -0,0 +1,25 @@
+package org.weekly.weekly.voucher.dto.request;
+
+import org.weekly.weekly.voucher.domain.DiscountType;
+import org.weekly.weekly.voucher.domain.Voucher;
+import org.weekly.weekly.voucher.exception.VoucherException;
+
+import java.time.LocalDate;
+import java.util.UUID;
+
+public class VoucherCreationRequest {
+ private final VoucherInfoRequest voucherInfoRequest;
+ private final DiscountType discountType;
+
+ public VoucherCreationRequest(VoucherInfoRequest voucherInfoRequest, DiscountType discountType) {
+ this.voucherInfoRequest = voucherInfoRequest;
+ this.discountType = discountType;
+ }
+
+ public Voucher toVoucher() {
+ UUID id = UUID.randomUUID();
+ long amount = voucherInfoRequest.getAmount();
+ LocalDate now = LocalDate.now();
+ return Voucher.of(id, amount, now, voucherInfoRequest.getExpiration(), discountType);
+ }
+}
diff --git a/src/main/java/org/weekly/weekly/voucher/dto/VoucherInfoRequest.java b/src/main/java/org/weekly/weekly/voucher/dto/request/VoucherInfoRequest.java
similarity index 50%
rename from src/main/java/org/weekly/weekly/voucher/dto/VoucherInfoRequest.java
rename to src/main/java/org/weekly/weekly/voucher/dto/request/VoucherInfoRequest.java
index b4401d7a97..3aecb596c7 100644
--- a/src/main/java/org/weekly/weekly/voucher/dto/VoucherInfoRequest.java
+++ b/src/main/java/org/weekly/weekly/voucher/dto/request/VoucherInfoRequest.java
@@ -1,17 +1,17 @@
-package org.weekly.weekly.voucher.dto;
+package org.weekly.weekly.voucher.dto.request;
-import org.weekly.weekly.ui.exception.ReadException;
+import org.weekly.weekly.ui.exception.InputValidator;
public class VoucherInfoRequest {
private static final String SPLIT_FORMAT = ",";
private static final int AMOUNT_NO = 0;
private static final int EXPIRATION = 1;
- private final String amount;
- private final String expiration;
+ private final long amount;
+ private final long expiration;
- private VoucherInfoRequest(String amount, String expiration) {
+ private VoucherInfoRequest(long amount, long expiration) {
this.amount = amount;
this.expiration = expiration;
}
@@ -20,21 +20,21 @@ public static VoucherInfoRequest of(String userInput) {
String[] inputs = userInput.split(SPLIT_FORMAT);
checkReadVoucherException(inputs);
- return new VoucherInfoRequest(inputs[AMOUNT_NO].trim(), inputs[EXPIRATION].trim());
+ return new VoucherInfoRequest(
+ Long.parseLong(inputs[AMOUNT_NO].trim()),
+ Long.parseLong(inputs[EXPIRATION].trim()));
}
- public String getAmount() {
+ public long getAmount() {
return amount;
}
- public String getExpiration() {
+ public long getExpiration() {
return expiration;
}
private static void checkReadVoucherException(String[] inputs) {
- ReadException.notVoucherInputSize(inputs);
- ReadException.notVoucherInputFormat(inputs);
+ InputValidator.notVoucherInputSize(inputs);
+ InputValidator.notNumber(inputs);
}
-
-
}
diff --git a/src/main/java/org/weekly/weekly/voucher/dto/response/VoucherCreationResponse.java b/src/main/java/org/weekly/weekly/voucher/dto/response/VoucherCreationResponse.java
new file mode 100644
index 0000000000..f02d0703a6
--- /dev/null
+++ b/src/main/java/org/weekly/weekly/voucher/dto/response/VoucherCreationResponse.java
@@ -0,0 +1,27 @@
+package org.weekly.weekly.voucher.dto.response;
+
+import org.weekly.weekly.voucher.domain.Voucher;
+import org.weekly.weekly.voucher.dto.Response;
+
+import java.text.MessageFormat;
+import java.time.LocalDate;
+import java.util.UUID;
+
+public class VoucherCreationResponse implements Response {
+ private final UUID id;
+ private final LocalDate registrationDate;
+ private final LocalDate expirationDate;
+ private final long amount;
+
+ public VoucherCreationResponse(Voucher voucher) {
+ this.id = voucher.getVoucherId();
+ this.registrationDate = voucher.getRegistrationDate();
+ this.expirationDate = voucher.getExpirationDate();
+ this.amount = voucher.getAmount();
+ }
+
+ @Override
+ public String getResult() {
+ return MessageFormat.format("[ID: {0}, 금액: {1}, 등록일자: {2}, 유효기간: {3}]", id, amount, registrationDate, expirationDate);
+ }
+}
diff --git a/src/main/java/org/weekly/weekly/voucher/dto/response/VouchersResponse.java b/src/main/java/org/weekly/weekly/voucher/dto/response/VouchersResponse.java
new file mode 100644
index 0000000000..64b16be1ce
--- /dev/null
+++ b/src/main/java/org/weekly/weekly/voucher/dto/response/VouchersResponse.java
@@ -0,0 +1,29 @@
+package org.weekly.weekly.voucher.dto.response;
+
+import org.weekly.weekly.util.PrintMessageType;
+import org.weekly.weekly.voucher.domain.Voucher;
+import org.weekly.weekly.voucher.dto.Response;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+public class VouchersResponse implements Response {
+ private final List result;
+
+ public VouchersResponse(List vouchers) {
+ this.result = vouchers.stream()
+ .map(VoucherCreationResponse::new)
+ .collect(Collectors.toUnmodifiableList());
+ }
+
+ public String getResult() {
+ if (result.isEmpty()) {
+ return PrintMessageType.NO_VOUCHER_DATAS.getMessage();
+ }
+
+
+ StringBuilder resultBuilder = new StringBuilder();
+ result.forEach(voucherResponse-> resultBuilder.append(voucherResponse.getResult()).append('\n'));
+ return resultBuilder.toString();
+ }
+}
diff --git a/src/main/java/org/weekly/weekly/voucher/exception/VoucherException.java b/src/main/java/org/weekly/weekly/voucher/exception/VoucherException.java
index 7d895df2b2..a9743019c0 100644
--- a/src/main/java/org/weekly/weekly/voucher/exception/VoucherException.java
+++ b/src/main/java/org/weekly/weekly/voucher/exception/VoucherException.java
@@ -2,36 +2,8 @@
import org.weekly.weekly.util.ExceptionMsg;
-import java.time.LocalDate;
-import java.util.function.Predicate;
-
-public class VoucherException {
- private static boolean isNumber(String userInput) {
- return userInput.chars().allMatch(value -> Character.isDigit(value));
- }
-
- private static void notNumber(String userInput) {
- if (!isNumber(userInput)) {
- throw new RuntimeException(ExceptionMsg.NOT_NUMBER_FORMAT.getMsg());
- }
- }
-
- private static void notRange(String userInput, Predicate ifCase) {
- if (ifCase.test(userInput)) {
- throw new RuntimeException(ExceptionMsg.NOT_NUMBER_FORMAT.getMsg());
- }
- }
-
- public static void notNumberFormat(String userInput, Predicate ifCase) {
- notNumber(userInput);
- notRange(userInput, ifCase);
- }
-
- public static void expirationError(LocalDate registrationDate, String expirationMonth) {
- LocalDate expirationDate = registrationDate.plusMonths(Long.parseLong(expirationMonth));
-
- if (registrationDate.isEqual(expirationDate) || registrationDate.isAfter(expirationDate)) {
- throw new RuntimeException(ExceptionMsg.EXPIRATION_ERROR.getMsg());
- }
+public class VoucherException extends RuntimeException{
+ public VoucherException(ExceptionMsg exceptionMsg) {
+ super(exceptionMsg.getMsg());
}
-}
\ No newline at end of file
+}
diff --git a/src/main/java/org/weekly/weekly/voucher/exception/VoucherValidator.java b/src/main/java/org/weekly/weekly/voucher/exception/VoucherValidator.java
new file mode 100644
index 0000000000..872558d980
--- /dev/null
+++ b/src/main/java/org/weekly/weekly/voucher/exception/VoucherValidator.java
@@ -0,0 +1,38 @@
+package org.weekly.weekly.voucher.exception;
+
+import org.weekly.weekly.util.ExceptionMsg;
+import org.weekly.weekly.voucher.domain.DiscountType;
+
+import java.time.LocalDate;
+import java.util.function.LongPredicate;
+
+public class VoucherValidator {
+ private static final int RANGE_START = 0;
+ private static final int RANGE_END = 100;
+
+ private VoucherValidator() {
+ throw new VoucherException(ExceptionMsg.UTIL_CLASS);
+ }
+
+ public static void validateExpiration(LocalDate registrationDate, long expirationMonth) {
+ LocalDate expirationDate = registrationDate.plusMonths(expirationMonth);
+
+ if (registrationDate.isEqual(expirationDate) || registrationDate.isAfter(expirationDate)) {
+ throw new VoucherException(ExceptionMsg.EXPIRATION_ERROR);
+ }
+ }
+ public static void validateAmount(DiscountType discountType, long amount) {
+ if (DiscountType.FIXED.equals(discountType)) {
+ notRange(amount, input -> input < RANGE_START);
+ return;
+ }
+
+ notRange(amount, input -> input < RANGE_START || input > RANGE_END);
+ }
+
+ private static void notRange(long userInput, LongPredicate ifCase) {
+ if (ifCase.test(userInput)) {
+ throw new VoucherException(ExceptionMsg.NOT_NUMBER_FORMAT);
+ }
+ }
+}
diff --git a/src/main/java/org/weekly/weekly/voucher/repository/JdbcVoucherRepository.java b/src/main/java/org/weekly/weekly/voucher/repository/JdbcVoucherRepository.java
new file mode 100644
index 0000000000..8892e68ef2
--- /dev/null
+++ b/src/main/java/org/weekly/weekly/voucher/repository/JdbcVoucherRepository.java
@@ -0,0 +1,123 @@
+package org.weekly.weekly.voucher.repository;
+
+import org.springframework.context.annotation.Profile;
+import org.springframework.dao.DataAccessException;
+import org.springframework.dao.EmptyResultDataAccessException;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.stereotype.Repository;
+import org.weekly.weekly.util.ExceptionMsg;
+import org.weekly.weekly.voucher.domain.DiscountType;
+import org.weekly.weekly.voucher.domain.Voucher;
+import org.weekly.weekly.voucher.exception.VoucherException;
+
+import javax.sql.DataSource;
+import java.nio.ByteBuffer;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Timestamp;
+import java.time.LocalDate;
+import java.util.List;
+import java.util.Optional;
+import java.util.UUID;
+
+@Profile("!dev")
+@Repository
+public class JdbcVoucherRepository implements VoucherRepository{
+ private final JdbcTemplate jdbcTemplate;
+
+ public JdbcVoucherRepository(DataSource dataSource) {
+ jdbcTemplate = new JdbcTemplate(dataSource);
+ }
+
+ @Override
+ public Optional findById(UUID voucherId) {
+ String sql = "SELECT * FROM vouchers WHERE voucher_id = UUID_TO_BIN(?)";
+ try {
+ return Optional.ofNullable(jdbcTemplate.queryForObject(sql, (rs, rowNum) -> mapToVoucher(rs), uuidToBytes(voucherId)));
+ } catch (EmptyResultDataAccessException e) {
+ return Optional.empty();
+ }
+ }
+
+ @Override
+ public List findAll() {
+ String sql = "SELECT * FROM vouchers";
+ return jdbcTemplate.query(sql, (rs, rowNum) -> mapToVoucher(rs));
+ }
+
+ @Override
+ public List findByDiscountType(DiscountType discountType) {
+ String sql = "SELECT * FROM vouchers WHERE discount = ?";
+ return jdbcTemplate.query(sql, (rs, rowNum) -> mapToVoucher(rs), discountType.name());
+ }
+
+ @Override
+ public Voucher insert(Voucher voucher) {
+ String sql = "INSERT INTO vouchers(voucher_id, amount, discount, registration_date, expiration_date) VALUES (UUID_TO_BIN(?), ?, ?, ?, ?)";
+ int update = 0;
+ try {
+ update = jdbcTemplate.update(sql,
+ uuidToBytes(voucher.getVoucherId()),
+ voucher.getAmount(),
+ voucher.getDiscountType().name(),
+ Timestamp.valueOf(voucher.getRegistrationDate().atStartOfDay()),
+ Timestamp.valueOf(voucher.getExpirationDate().atStartOfDay()));
+ } catch(DataAccessException dataAccessException) {
+ throw new VoucherException(ExceptionMsg.SQL_INSERT_ERROR);
+ }
+
+ if (update != 1) {
+ throw new VoucherException(ExceptionMsg.SQL_ERROR);
+ }
+ return voucher;
+ }
+
+ @Override
+ public Voucher update(Voucher voucher) {
+ String sql = "UPDATE vouchers SET amount = ?, discount = ?, expiration_date = ? WHERE voucher_id = UUID_TO_BIN(?)";
+
+ int update = jdbcTemplate.update(sql,
+ voucher.getAmount(),
+ voucher.getDiscountType().name(),
+ Timestamp.valueOf(voucher.getExpirationDate().atStartOfDay()),
+ uuidToBytes(voucher.getVoucherId()));
+ if (update != 1) {
+ throw new VoucherException(ExceptionMsg.SQL_ERROR);
+ }
+ return voucher;
+ }
+
+ @Override
+ public void deleteById(UUID voucherId) {
+ String sql = "DELETE FROM vouchers WHERE voucher_id = UUID_TO_BIN(?)";
+ jdbcTemplate.update(sql, uuidToBytes(voucherId));
+ }
+
+ @Override
+ public void deleteAll() {
+ String sql = "DELETE FROM vouchers";
+ jdbcTemplate.update(sql);
+ }
+
+ public static UUID toUUID(byte[] bytes) {
+ var buffer = ByteBuffer.wrap(bytes);
+ return new UUID(buffer.getLong(), buffer.getLong());
+ }
+
+ private byte[] uuidToBytes(UUID voucherId) {
+ return voucherId.toString().getBytes();
+ }
+
+ private Voucher mapToVoucher(ResultSet resultSet) throws SQLException {
+ UUID voucherId = toUUID(resultSet.getBytes("voucher_id"));
+ long amount = resultSet.getLong("amount");
+ DiscountType discountType = DiscountType.getDiscountTypeByName(resultSet.getString("discount"));
+ LocalDate registrationDate = resultSet.getTimestamp("registration_date") == null ? null : resultSet.getTimestamp("registration_date").toLocalDateTime().toLocalDate();
+ LocalDate expirationDate = resultSet.getTimestamp("expiration_date") == null ? null : resultSet.getTimestamp("expiration_date").toLocalDateTime().toLocalDate();
+
+ return new Voucher(voucherId,amount, registrationDate, expirationDate, discountType.getNewInstance());
+ }
+
+
+
+}
diff --git a/src/main/java/org/weekly/weekly/voucher/repository/MemoryVoucherRepository.java b/src/main/java/org/weekly/weekly/voucher/repository/MemoryVoucherRepository.java
new file mode 100644
index 0000000000..e1b8d1bc70
--- /dev/null
+++ b/src/main/java/org/weekly/weekly/voucher/repository/MemoryVoucherRepository.java
@@ -0,0 +1,62 @@
+package org.weekly.weekly.voucher.repository;
+
+import org.springframework.context.annotation.Profile;
+import org.springframework.stereotype.Repository;
+import org.weekly.weekly.util.ExceptionMsg;
+import org.weekly.weekly.voucher.domain.DiscountType;
+import org.weekly.weekly.voucher.domain.Voucher;
+import org.weekly.weekly.voucher.exception.VoucherException;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.UUID;
+import java.util.concurrent.ConcurrentHashMap;
+
+@Profile("dev")
+@Repository
+public class MemoryVoucherRepository implements VoucherRepository{
+ private final Map storages = new ConcurrentHashMap<>();
+
+ public Voucher insert(Voucher voucher) {
+ validateUUID(voucher.getVoucherId());
+ storages.put(voucher.getVoucherId(), voucher);
+ return voucher;
+ }
+
+ public Optional findById(UUID voucherId) {
+ return Optional.ofNullable(storages.get(voucherId));
+ }
+
+ public List findAll() {
+ return storages.values().stream()
+ .toList();
+ }
+
+ @Override
+ public List findByDiscountType(DiscountType discountType) {
+ return null;
+ }
+
+ @Override
+ public Voucher update(Voucher voucher) {
+ return null;
+ }
+
+ @Override
+ public void deleteById(UUID voucherId) {
+
+ }
+
+ @Override
+ public void deleteAll() {
+
+ }
+
+ private void validateUUID(UUID uuid) {
+ Optional voucherOptional = findById(uuid);
+ if (voucherOptional.isPresent()) {
+ throw new VoucherException(ExceptionMsg.VOUCHER_EXIST);
+ }
+ }
+}
diff --git a/src/main/java/org/weekly/weekly/voucher/repository/VoucherRepository.java b/src/main/java/org/weekly/weekly/voucher/repository/VoucherRepository.java
index a1a8c0aa38..0e794a4f2f 100644
--- a/src/main/java/org/weekly/weekly/voucher/repository/VoucherRepository.java
+++ b/src/main/java/org/weekly/weekly/voucher/repository/VoucherRepository.java
@@ -1,26 +1,22 @@
package org.weekly.weekly.voucher.repository;
-import org.springframework.stereotype.Repository;
+import org.weekly.weekly.voucher.domain.DiscountType;
import org.weekly.weekly.voucher.domain.Voucher;
-import java.util.*;
-import java.util.concurrent.ConcurrentHashMap;
+import java.util.List;
+import java.util.Optional;
+import java.util.UUID;
-@Repository
-public class VoucherRepository {
- private final Map storages = new ConcurrentHashMap<>();
+public interface VoucherRepository {
+ Voucher insert(Voucher voucher);
+ Optional findById(UUID voucherId);
+ List findAll();
- public Voucher insert(Voucher voucher) {
- storages.put(voucher.getVoucherId(), voucher);
- return voucher;
- }
+ List findByDiscountType(DiscountType discountType);
- public Optional findById(UUID voucherId) {
- return Optional.ofNullable(storages.get(voucherId));
- }
+ Voucher update(Voucher voucher);
- public List findAll() {
- return storages.values().stream()
- .toList();
- }
+ void deleteById(UUID voucherId);
+
+ void deleteAll();
}
diff --git a/src/main/java/org/weekly/weekly/voucher/service/VoucherService.java b/src/main/java/org/weekly/weekly/voucher/service/VoucherService.java
index e1893b22a1..a79e89cd54 100644
--- a/src/main/java/org/weekly/weekly/voucher/service/VoucherService.java
+++ b/src/main/java/org/weekly/weekly/voucher/service/VoucherService.java
@@ -1,15 +1,13 @@
package org.weekly.weekly.voucher.service;
import org.springframework.stereotype.Service;
-import org.weekly.weekly.util.ExceptionMsg;
import org.weekly.weekly.voucher.domain.Voucher;
-import org.weekly.weekly.voucher.dto.VoucherDto;
-import org.weekly.weekly.voucher.dto.CreateResponse;
-import org.weekly.weekly.voucher.dto.ListResponse;
+import org.weekly.weekly.voucher.dto.request.VoucherCreationRequest;
+import org.weekly.weekly.voucher.dto.response.VoucherCreationResponse;
+import org.weekly.weekly.voucher.dto.response.VouchersResponse;
import org.weekly.weekly.voucher.repository.VoucherRepository;
import java.util.List;
-import java.util.Optional;
@Service
public class VoucherService {
@@ -19,22 +17,16 @@ public VoucherService(VoucherRepository voucherRepository) {
this.voucherRepository = voucherRepository;
}
- public CreateResponse insertVoucher(VoucherDto voucherDto) {
- validateVoucher(voucherDto);
- Voucher voucher = voucherDto.parseToVoucher();
- this.voucherRepository.insert(voucher);
- return new CreateResponse(voucher);
+ public VoucherCreationResponse insertVoucher(VoucherCreationRequest voucherCreationRequest) {
+ Voucher voucher = voucherCreationRequest.toVoucher();
+ voucherRepository.insert(voucher);
+ return new VoucherCreationResponse(voucher);
}
- public ListResponse getVouchers() {
- List vouchers = this.voucherRepository.findAll();
- return new ListResponse(vouchers);
+ public VouchersResponse getVouchers() {
+ List vouchers = voucherRepository.findAll();
+ return new VouchersResponse(vouchers);
}
- private void validateVoucher(VoucherDto voucherDto) {
- Optional voucherOptional = this.voucherRepository.findById(voucherDto.getVoucherId());
- if (voucherOptional.isPresent()) {
- throw new RuntimeException(ExceptionMsg.VOUCHER_EXIST.getMsg());
- }
- }
+
}
diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties
deleted file mode 100644
index 8b13789179..0000000000
--- a/src/main/resources/application.properties
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml
new file mode 100644
index 0000000000..90244d6551
--- /dev/null
+++ b/src/main/resources/application.yaml
@@ -0,0 +1,46 @@
+spring.config.activate.on-profile: default
+command:
+ write: system
+ read: scanner
+
+spring:
+ datasource:
+ driver-class-name: com.mysql.cj.jdbc.Driver
+ url: jdbc:mysql://localhost:3306/voucher_mgmt?createDatabaseIfNotExist=true
+ username: "root"
+ password: "qwe123"
+
+ sql:
+ init:
+ mode: always
+
+---
+
+spring.config.activate.on-profile: dev
+command:
+ write: system
+ read: console
+
+---
+
+spring.config.activate.on-profile: local
+command:
+ write: system
+ read: buffer
+
+---
+
+spring.config.activate.on-profile: test
+command:
+ write: system
+ read: scanner
+
+spring:
+ datasource:
+ url: jdbc:tc:mysql:8://test
+
+ sql:
+ init:
+ mode: always
+
+
diff --git a/src/main/resources/logback.xml b/src/main/resources/logback.xml
index c28bb18107..41b5312d80 100644
--- a/src/main/resources/logback.xml
+++ b/src/main/resources/logback.xml
@@ -18,4 +18,4 @@
-
\ No newline at end of file
+
diff --git a/src/main/resources/schema.sql b/src/main/resources/schema.sql
new file mode 100644
index 0000000000..0b88d26b44
--- /dev/null
+++ b/src/main/resources/schema.sql
@@ -0,0 +1,29 @@
+DROP TABLE IF EXISTS customers;
+CREATE TABLE customers (
+ customer_id BINARY(16) PRIMARY KEY,
+ name varchar(20) NOT NULL,
+ email varchar(50) NOT NULL,
+ create_at datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
+ CONSTRAINT unq_user_email UNIQUE (email)
+);
+
+INSERT INTO customers(customer_id, name, email)
+VALUES (uuid_to_bin(UUID()), 'tester00', 'test00@gmail.com'),
+ (uuid_to_bin(UUID()), 'tester01', 'test01@gmail.com'),
+ (uuid_to_bin(UUID()), 'tester02', 'test02@gmail.com');
+
+
+
+DROP TABLE IF EXISTS vouchers;
+CREATE TABLE vouchers (
+ voucher_id BINARY(16) PRIMARY KEY,
+ amount bigint NOT NULL,
+ discount enum('FIXED', 'PERCENT') NOT NULL,
+ registration_date datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
+ expiration_date datetime(6) NOT NULL
+);
+
+INSERT INTO vouchers (voucher_id, amount, discount, expiration_date)
+VALUES (uuid_to_bin(UUID()), 50, 'PERCENT', DATE_ADD(CURRENT_TIMESTAMP(6), INTERVAL 7 DAY)),
+ (uuid_to_bin(UUID()), 100000, 'FIXED', DATE_ADD(CURRENT_TIMESTAMP(6), INTERVAL 7 DAY)),
+ (uuid_to_bin(UUID()), 80, 'PERCENT', DATE_ADD(CURRENT_TIMESTAMP(6), INTERVAL 7 DAY));
\ No newline at end of file
diff --git a/src/test/java/org/weekly/weekly/customer/CustomerTest.java b/src/test/java/org/weekly/weekly/customer/CustomerTest.java
new file mode 100644
index 0000000000..a809768083
--- /dev/null
+++ b/src/test/java/org/weekly/weekly/customer/CustomerTest.java
@@ -0,0 +1,27 @@
+package org.weekly.weekly.customer;
+
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.ValueSource;
+import org.weekly.weekly.customer.domain.Customer;
+import org.weekly.weekly.customer.exception.CustomerException;
+
+import java.util.UUID;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import static org.hamcrest.Matchers.*;
+
+public class CustomerTest {
+
+ @Test
+ void 회원생성_성공_테스트() {
+ assertThat(Customer.of(UUID.randomUUID(), "hello", "email@gmail.com"), instanceOf(Customer.class));
+ }
+
+ @ParameterizedTest
+ @ValueSource(strings = {"123", "123@", "213@n", "abc@naver.", "abc@naver.c", "abc@naver.comc"})
+ void 회원생성_실패_테스트(String email) {
+ assertThatThrownBy(()-> Customer.of(UUID.randomUUID(), "hello", email)).isInstanceOf(CustomerException.class);
+ }
+}
diff --git a/src/test/java/org/weekly/weekly/customer/JdbcCustomerRepositoryTest.java b/src/test/java/org/weekly/weekly/customer/JdbcCustomerRepositoryTest.java
new file mode 100644
index 0000000000..54b4f22fed
--- /dev/null
+++ b/src/test/java/org/weekly/weekly/customer/JdbcCustomerRepositoryTest.java
@@ -0,0 +1,128 @@
+package org.weekly.weekly.customer;
+
+import org.junit.jupiter.api.*;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.ActiveProfiles;
+import org.testcontainers.junit.jupiter.Testcontainers;
+import org.weekly.weekly.customer.domain.Customer;
+import org.weekly.weekly.customer.exception.CustomerException;
+import org.weekly.weekly.customer.repository.JdbcCustomerRepository;
+
+import java.util.List;
+import java.util.Optional;
+import java.util.UUID;
+
+import static org.assertj.core.api.Assertions.assertThatCode;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.samePropertyValuesAs;
+
+@Testcontainers
+@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
+@ActiveProfiles("test")
+@SpringBootTest
+class JdbcCustomerRepositoryTest {
+ @Autowired
+ private JdbcCustomerRepository jdbcCustomerRepository;
+
+ Customer customer;
+
+ @BeforeEach
+ void setUp() {
+ customer = Customer.of(UUID.randomUUID(), "tester", "test@naver.com");
+ }
+
+ @AfterEach
+ void deleteCustomer() {
+ assertThatCode(() -> jdbcCustomerRepository.deleteByEmail(customer.getEmail()));
+ }
+
+ @Test
+ void 전체_회원_검색_테스트() {
+ // Given
+ Customer insertCustomer = jdbcCustomerRepository.insert(customer);
+
+ // When + Then
+ List customers = jdbcCustomerRepository.findAll();
+ assertThat(customers.isEmpty(), is(false));
+ }
+
+ @Test
+ void 회원_등록성공_테스트() {
+ // Given
+ Customer insertCustomer = jdbcCustomerRepository.insert(customer);
+
+ // When
+ Optional findCustomer = jdbcCustomerRepository.findByEmail(insertCustomer.getEmail());
+
+ // Then
+ assertThat(findCustomer.isEmpty(), is(false));
+ assertThat(findCustomer.get(), samePropertyValuesAs(insertCustomer));
+ }
+
+ @Test
+ void 이메일_회원_검색_성공_테스트() {
+ // Given
+ Customer insertCustomer = jdbcCustomerRepository.insert(customer);
+
+ // When
+ Optional customers = jdbcCustomerRepository.findByEmail(insertCustomer.getEmail());
+
+ // Then
+ assertThat(customers.isEmpty(), is(false));
+ }
+
+ @Test
+ void 이메일_회원_검색_실패_테스트() {
+ Optional customers = jdbcCustomerRepository.findByEmail(customer.getEmail());
+ assertThat(customers.isEmpty(), is(true));
+ }
+
+ @Test
+ void 회원_삭제_성공_테스트() {
+ // Given
+ Customer insertCustomer = jdbcCustomerRepository.insert(customer);
+ Optional findCustomer = jdbcCustomerRepository.findByEmail(insertCustomer.getEmail());
+ assertThat(findCustomer.isPresent(), is(true));
+
+ // When
+ jdbcCustomerRepository.deleteByEmail(findCustomer.get().getEmail());
+
+ // THen
+ Optional deleteCustomer = jdbcCustomerRepository.findByEmail(insertCustomer.getEmail());
+ assertThat(deleteCustomer.isEmpty(), is(true));
+ }
+
+ @Test
+ void 회원_삭제_실패_테스트() {
+ // when
+ jdbcCustomerRepository.deleteByEmail(customer.getEmail());
+
+ }
+
+ @Test
+ void 전체_회원_삭제_테스트() {
+ // Given
+ jdbcCustomerRepository.deleteAll();
+
+ List customers = jdbcCustomerRepository.findAll();
+ assertThat(customers.isEmpty(), is(true));
+ }
+
+ @Test
+ void 회원_닉네임_업데이트_테스트() {
+ // Given
+ String newName = "newName";
+ Customer insertCusomter = jdbcCustomerRepository.insert(customer);
+
+ // When
+ jdbcCustomerRepository.update(insertCusomter,newName);
+
+ // Then
+ Optional updateCustomer = jdbcCustomerRepository.findByEmail(newName);
+ assertThat(updateCustomer.isPresent(), is(true));
+ assertThat(updateCustomer.get().getEmail(), is(newName));
+ }
+}
diff --git a/src/test/java/org/weekly/weekly/ui/ReadExceptionTest.java b/src/test/java/org/weekly/weekly/ui/ReadExceptionTest.java
index 27020b2670..ec1ee12655 100644
--- a/src/test/java/org/weekly/weekly/ui/ReadExceptionTest.java
+++ b/src/test/java/org/weekly/weekly/ui/ReadExceptionTest.java
@@ -2,7 +2,7 @@
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
-import org.weekly.weekly.ui.exception.ReadException;
+import org.weekly.weekly.ui.exception.InputValidator;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
@@ -10,7 +10,7 @@ public class ReadExceptionTest {
@ParameterizedTest
@ValueSource(strings = {"", " "})
void 사용자가_빈값이나_입력오류났을때_예외발생(String userInput) {
- assertThatThrownBy(()-> ReadException.isEmpty(userInput))
+ assertThatThrownBy(()-> InputValidator.isEmpty(userInput))
.isInstanceOf(RuntimeException.class);
}
}
diff --git a/src/test/java/org/weekly/weekly/util/DiscountMapTest.java b/src/test/java/org/weekly/weekly/util/DiscountMapTest.java
index 56bbb7d0e7..3443ee7c77 100644
--- a/src/test/java/org/weekly/weekly/util/DiscountMapTest.java
+++ b/src/test/java/org/weekly/weekly/util/DiscountMapTest.java
@@ -3,6 +3,7 @@
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
+import org.weekly.weekly.voucher.domain.DiscountType;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
@@ -17,7 +18,7 @@ public class DiscountMapTest {
})
void 사용자_입력이_할인_맵에_없으면_예외발생(String userInput) {
// when + then
- assertThatThrownBy(()-> DiscountType.getDiscountMap(userInput))
+ assertThatThrownBy(()-> DiscountType.getDiscountTypeByNumber(userInput))
.isInstanceOf(RuntimeException.class);
}
@@ -29,8 +30,8 @@ public class DiscountMapTest {
String percentUserInput = "2";
// when
- DiscountType fixedDiscount = DiscountType.getDiscountMap(fixedUserInput);
- DiscountType percentDiscount = DiscountType.getDiscountMap(percentUserInput);
+ DiscountType fixedDiscount = DiscountType.getDiscountTypeByNumber(fixedUserInput);
+ DiscountType percentDiscount = DiscountType.getDiscountTypeByNumber(percentUserInput);
// then
assertThat(fixedDiscount).isEqualTo(DiscountType.FIXED);
diff --git a/src/test/java/org/weekly/weekly/voucher/JdbcVoucherRepositoryTest.java b/src/test/java/org/weekly/weekly/voucher/JdbcVoucherRepositoryTest.java
new file mode 100644
index 0000000000..6a47bcc496
--- /dev/null
+++ b/src/test/java/org/weekly/weekly/voucher/JdbcVoucherRepositoryTest.java
@@ -0,0 +1,157 @@
+package org.weekly.weekly.voucher;
+
+import org.junit.jupiter.api.*;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.CsvSource;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.ActiveProfiles;
+import org.testcontainers.junit.jupiter.Testcontainers;
+import org.weekly.weekly.voucher.domain.DiscountType;
+import org.weekly.weekly.voucher.domain.Voucher;
+import org.weekly.weekly.voucher.repository.JdbcVoucherRepository;
+
+import java.time.LocalDate;
+import java.util.List;
+import java.util.Optional;
+import java.util.UUID;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.samePropertyValuesAs;
+
+@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
+@ActiveProfiles("test")
+@Testcontainers
+@SpringBootTest
+class JdbcVoucherRepositoryTest{
+ @Autowired
+ private JdbcVoucherRepository jdbcVoucherRepository;
+
+ Voucher fixedVoucher;
+ Voucher percentVoucher;
+
+ @BeforeEach
+ void setUp() {
+ fixedVoucher = Voucher.of(UUID.randomUUID(), 10000, LocalDate.now(), 7, DiscountType.FIXED);
+ percentVoucher = Voucher.of(UUID.randomUUID(), 50, LocalDate.now(), 7, DiscountType.PERCENT);
+ }
+
+ @Test
+ @Order(1)
+ void 전체_바우처_검색_테스트() {
+ List vouchers = jdbcVoucherRepository.findAll();
+ assertThat(vouchers.isEmpty(), is(false));
+ }
+
+ @Test
+ @Order(1)
+ void 아이디를_통한_검색_실패_테스트() {
+ Optional voucher = jdbcVoucherRepository.findById(fixedVoucher.getVoucherId());
+ assertThat(voucher.isEmpty(), is(true));
+ }
+
+ @Test
+ @Order(1)
+ void 아이디를_통한_검색_성공_테스트() {
+ Optional voucher = jdbcVoucherRepository.findById(fixedVoucher.getVoucherId());
+ assertThat(voucher.isPresent(), is(false));
+ }
+
+ @Test
+ @Order(1)
+ void 할인정책을_통한_검색_테스트() {
+ List vouchers = jdbcVoucherRepository.findByDiscountType(percentVoucher.getDiscountType());
+
+ assertThat(vouchers.isEmpty(), is(false));
+
+ vouchers.stream()
+ .forEach(voucher -> assertThat(voucher.getDiscountType(), is(DiscountType.PERCENT)));
+ }
+
+ @Test
+ @Order(2)
+ void 할인바우처_등록성공_테스트() {
+ Voucher voucher = jdbcVoucherRepository.insert(percentVoucher);
+
+ Optional findVoucher = jdbcVoucherRepository.findById(percentVoucher.getVoucherId());
+
+ assertThat(findVoucher.isEmpty(), is(false));
+ assertThat(findVoucher.get(), samePropertyValuesAs(voucher));
+ }
+
+ @Test
+ @Order(2)
+ void 고정바우처_등록성공_테스트() {
+ Voucher voucher = jdbcVoucherRepository.insert(fixedVoucher);
+
+ Optional findVoucher = jdbcVoucherRepository.findById(fixedVoucher.getVoucherId());
+
+ assertThat(findVoucher.isEmpty(), is(false));
+ assertThat(findVoucher.get(), samePropertyValuesAs(voucher));
+ }
+
+
+ @ParameterizedTest
+ @CsvSource({"5000, 0", "15000, 5000"})
+ @Order(3)
+ void 고정바우처_정보_업데이트_테스트(int amount, long reaminExpected) {
+ // Given
+ jdbcVoucherRepository.insert(fixedVoucher);
+
+ // When
+ long remain = fixedVoucher.applyDiscount(amount);
+ jdbcVoucherRepository.update(fixedVoucher);
+ Optional voucher = jdbcVoucherRepository.findById(fixedVoucher.getVoucherId());
+
+ // Then
+ assertThat(remain, is(reaminExpected));
+ assertThat(voucher.isEmpty(), is(false));
+ assertThat(voucher.get(), samePropertyValuesAs(fixedVoucher));
+ }
+
+ @ParameterizedTest
+ @CsvSource({"3000, 1500", "1000, 500"})
+ @Order(3)
+ void 퍼센트바우처_정보_업데이트_테스트(int amount, long reaminExpected) {
+ // Given
+ jdbcVoucherRepository.insert(percentVoucher);
+
+ // When
+ long remain = percentVoucher.applyDiscount(amount);
+ jdbcVoucherRepository.update(percentVoucher);
+ Optional voucher = jdbcVoucherRepository.findById(percentVoucher.getVoucherId());
+
+ // Then
+ assertThat(remain, is(reaminExpected));
+ assertThat(voucher.isEmpty(), is(false));
+ assertThat(voucher.get(), samePropertyValuesAs(percentVoucher));
+ }
+
+ @Test
+ @Order(4)
+ void 바우처_삭제_테스트() {
+ // Given
+ Voucher voucher = jdbcVoucherRepository.insert(percentVoucher);
+ Optional findVoucher = jdbcVoucherRepository.findById(voucher.getVoucherId());
+ assertThat(findVoucher.isPresent(), is(true));
+
+ // when
+ jdbcVoucherRepository.deleteById(voucher.getVoucherId());
+
+ // Then
+ Optional deleteVoucher = jdbcVoucherRepository.findById(voucher.getVoucherId());
+ assertThat(deleteVoucher.isEmpty(), is(true));
+ }
+
+ @Test
+ @Order(5)
+ void 전체_바우처_삭제_테스트() {
+ // Given
+ jdbcVoucherRepository.deleteAll();
+
+ // when
+ List vouchers = jdbcVoucherRepository.findAll();
+ assertThat(vouchers.isEmpty(), is(true));
+ }
+}
diff --git a/src/test/java/org/weekly/weekly/voucher/VoucherTest.java b/src/test/java/org/weekly/weekly/voucher/VoucherTest.java
index 0947d69ba0..d786525500 100644
--- a/src/test/java/org/weekly/weekly/voucher/VoucherTest.java
+++ b/src/test/java/org/weekly/weekly/voucher/VoucherTest.java
@@ -5,14 +5,11 @@
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;
import org.junit.jupiter.params.provider.ValueSource;
-import org.weekly.weekly.util.DiscountType;
-import org.weekly.weekly.voucher.domain.Discount;
-import org.weekly.weekly.voucher.domain.FixedDiscount;
-import org.weekly.weekly.voucher.domain.PercentDiscount;
+import org.weekly.weekly.voucher.domain.DiscountType;
import org.weekly.weekly.voucher.domain.Voucher;
-import org.weekly.weekly.voucher.dto.VoucherDto;
-import org.weekly.weekly.voucher.dto.VoucherInfoRequest;
-import org.weekly.weekly.voucher.repository.VoucherRepository;
+import org.weekly.weekly.voucher.dto.request.VoucherCreationRequest;
+import org.weekly.weekly.voucher.dto.request.VoucherInfoRequest;
+import org.weekly.weekly.voucher.repository.MemoryVoucherRepository;
import java.time.LocalDate;
import java.util.UUID;
@@ -20,11 +17,11 @@
import static org.assertj.core.api.Assertions.*;
public class VoucherTest {
- private VoucherRepository voucherRepository;
+ private MemoryVoucherRepository voucherRepository;
@BeforeEach
void setVoucherRepository() {
- voucherRepository = new VoucherRepository();
+ voucherRepository = new MemoryVoucherRepository();
}
@ParameterizedTest
@@ -33,20 +30,18 @@ void setVoucherRepository() {
"10,1: 1"
}, delimiter = ':')
void 바우처가_이미_존재하면_예외발생(String userInput, String no) {
- assertThatCode(()-> {
- // Given
- UUID voucherId = UUID.randomUUID();
- VoucherInfoRequest voucherInfo = VoucherInfoRequest.of(userInput);
- Discount discount = DiscountType.getDiscountMap(no).getCls().getDeclaredConstructor().newInstance();
- LocalDate localDate = LocalDate.now();
+ // Given
+ UUID voucherId = UUID.randomUUID();
+ VoucherInfoRequest voucherInfo = VoucherInfoRequest.of(userInput);
+ DiscountType discount = DiscountType.getDiscountTypeByNumber(no);
+ LocalDate now = LocalDate.now();
+ Voucher voucher = Voucher.of(voucherId, voucherInfo.getAmount(), now, voucherInfo.getExpiration(), discount);
- // when
- VoucherDto voucherDto = VoucherDto.parseDto(voucherId, voucherInfo, discount, localDate);
- voucherRepository.insert(voucherDto.parseToVoucher());
+ // when
+ voucherRepository.insert(voucher);
- // then
- assertThat(voucherRepository.findById(voucherId).isPresent()).isTrue();
- }).doesNotThrowAnyException();
+ // then
+ assertThat(voucherRepository.findById(voucherId).isPresent()).isTrue();
}
@ParameterizedTest
@@ -57,13 +52,15 @@ void setVoucherRepository() {
})
void 바우처_발행시간이_유효시간보다_느리면_예외발생(String userInput) {
// Given
- UUID voucherId = UUID.randomUUID();
- LocalDate localDate = LocalDate.now();
- Discount discount = new FixedDiscount();
+// UUID voucherId = UUID.randomUUID();
+// LocalDate localDate = LocalDate.now();
+ DiscountType discount = DiscountType.FIXED;
VoucherInfoRequest voucherInfo = VoucherInfoRequest.of(userInput);
+ VoucherCreationRequest request = new VoucherCreationRequest(voucherInfo, discount);
+
// when + then
- assertThatThrownBy(()->VoucherDto.parseDto(voucherId, voucherInfo, discount, localDate))
+ assertThatThrownBy(()->request.toVoucher())
.isInstanceOf(RuntimeException.class);
}
@@ -72,17 +69,19 @@ class 고정바우처_테스트 {
@ParameterizedTest
@ValueSource(strings = {
"-1,12",
- " asfd, 1"
+ " -50, 1"
})
void 바우처_금액이_자연수가_아니면_예외발생(String userInput) {
// Given
- UUID voucherId = UUID.randomUUID();
- LocalDate localDate = LocalDate.now();
- Discount discount = new FixedDiscount();
- VoucherInfoRequest voucherInfo = VoucherInfoRequest.of(userInput);
+ DiscountType discountType = DiscountType.FIXED;
- // when + then
- assertThatThrownBy(()->VoucherDto.parseDto(voucherId, voucherInfo, discount, localDate))
+ VoucherInfoRequest voucherInfoRequest = VoucherInfoRequest.of(userInput);
+
+ // when
+ VoucherCreationRequest request = new VoucherCreationRequest(voucherInfoRequest, discountType);
+
+ // then
+ assertThatThrownBy(()-> request.toVoucher())
.isInstanceOf(RuntimeException.class);
}
@@ -93,10 +92,8 @@ class 고정바우처_테스트 {
})
void 고정_할인금액_적용하여_결과확인(int userInput, int discountMoney, int result) {
// Given
- Discount discount = new FixedDiscount();
LocalDate current = LocalDate.now();
- LocalDate next = current.plusMonths(1);
- Voucher voucher = new Voucher(UUID.randomUUID(), discountMoney, current, next, discount);
+ Voucher voucher = Voucher.of(UUID.randomUUID(), discountMoney, current, 1, DiscountType.FIXED);
// when
long afterApply = voucher.applyDiscount(userInput);
@@ -116,12 +113,12 @@ class 퍼센트바우처_테스트 {
void 바우처_퍼센트값이_자연수가_아니면_예외발생(String userInput) {
// Given
UUID voucherId = UUID.randomUUID();
- LocalDate localDate = LocalDate.now();
- Discount discount = new PercentDiscount();
+ LocalDate now = LocalDate.now();
VoucherInfoRequest voucherInfo = VoucherInfoRequest.of(userInput);
+
// when + then
- assertThatThrownBy(()->VoucherDto.parseDto(voucherId, voucherInfo, discount, localDate))
+ assertThatThrownBy(()->Voucher.of(voucherId, voucherInfo.getAmount(), now, 1, DiscountType.PERCENT))
.isInstanceOf(RuntimeException.class);
}
@@ -134,9 +131,7 @@ class 퍼센트바우처_테스트 {
void 퍼센트_할인금액_적용하여_결과확인(int userInput, int discountMoney, int result) {
// Given
LocalDate current = LocalDate.now();
- LocalDate next = current.plusMonths(1);
- Discount discount = new PercentDiscount();
- Voucher voucher = new Voucher(UUID.randomUUID(), discountMoney, current, next, discount);
+ Voucher voucher = Voucher.of(UUID.randomUUID(), discountMoney, current, 1, DiscountType.PERCENT);
// when
long afterApply = voucher.applyDiscount(userInput);