Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[4기 - 황창현] Week2-3 JdbcTemplate을 활용한 바우처 CRUD 기능 구현 #774

Merged
merged 63 commits into from
Jul 16, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
63 commits
Select commit Hold shift + click to select a range
15ece18
test: 고정 할인, 퍼센트 할인 도메인 성공 케이스 작성
Hchanghyeon Jul 2, 2023
86816d3
fix: PercentDiscount 계산 로직 에러 수정
Hchanghyeon Jul 2, 2023
f4aa980
test: voucher를 생성할 때 발생하는 실패케이스(예외) 작성
Hchanghyeon Jul 2, 2023
898f2d3
test: 팩토리에서 Voucher를 생성하는 성공 테스트 작성
Hchanghyeon Jul 2, 2023
7a0fa27
test: 파일, 메모리에 바우처 저장 및 조회 테스트 케이스 작성
Hchanghyeon Jul 2, 2023
6fdbded
fix: 파일에서 읽어드린 바우처의 UUID가 일치하지 않는 값 로직 변경하여 정상적으로 수정
Hchanghyeon Jul 2, 2023
d578612
고객 블랙리스트 명단 조회 Repository 테스트 생성
Hchanghyeon Jul 2, 2023
2ed58be
test: 고객을 생성하는 Cutomer 도메인 테스트 생성
Hchanghyeon Jul 2, 2023
3c9ab64
test: 바우처 조회 VoucherService 테스트 코드 작성
Hchanghyeon Jul 3, 2023
1b660c2
test: enum 타입이 아닐 경우 발생하는 예외 케이스 테스트 작성
Hchanghyeon Jul 3, 2023
5aea65c
test: 블랙리스트인 고객을 조회하는 서비스 테스트 작성
Hchanghyeon Jul 3, 2023
5b0f1ab
refactor: 길어지는 코드 개행 처리, Assertions import처리
Hchanghyeon Jul 3, 2023
a85cc85
refactor: customer 도메인 필드 추가, blacklist 가져올 때 Map에서 List로 변경
Hchanghyeon Jul 3, 2023
dfb345f
feat: jdbc 연결 설정 및 의존성 추가
Hchanghyeon Jul 3, 2023
36065d5
feat: 고객 Repository JDBC Template으로 Crud 구현
Hchanghyeon Jul 4, 2023
353ffe3
fix: customerRepository 추가로 인해 발생되는 테스트코드 에러 수정
Hchanghyeon Jul 4, 2023
1fec818
feat: Customer CRUD 관련된 서비스 로직 구현
Hchanghyeon Jul 4, 2023
00f3125
feat: Customer CRUD 관련된 컨트롤러 로직 구현
Hchanghyeon Jul 4, 2023
7fc19a1
feat: Console 기능 분리, Customer CRUD View 구현
Hchanghyeon Jul 4, 2023
96ca0b2
test: SpringBootTest 사용하는 클래스에만 적용
Hchanghyeon Jul 4, 2023
5d4d001
BDDMockito로 변경
Hchanghyeon Jul 4, 2023
291c3fe
docs: gitignore에 file추가
Hchanghyeon Jul 4, 2023
a7b04d4
test: Customer CRUD 서비스 테스트 구현
Hchanghyeon Jul 4, 2023
a822307
test: BDDMokito 형식으로 변환
Hchanghyeon Jul 4, 2023
362211a
test: 고객 CRUD 테스트 코드 수정
Hchanghyeon Jul 6, 2023
541e39b
refactor: enum 정적 팩토리 메소드 네이밍 변경
Hchanghyeon Jul 6, 2023
b5d1f7f
refactor: 검증을 dto를 생성하는 부분에서 하지 않고 input쪽으로 넘겨서 검증하는 로직으로 수정
Hchanghyeon Jul 6, 2023
c637baa
refactor: builder 패턴 적용
Hchanghyeon Jul 6, 2023
b87e826
refactor: Customer Repository SQL문 수정
Hchanghyeon Jul 6, 2023
376e76e
refactor: Validator 클래스안의 메소드 네이밍 변경 및 구조 단순화
Hchanghyeon Jul 6, 2023
7670cdf
test: given when then 수정
Hchanghyeon Jul 6, 2023
7f7b3df
refactor: repository에서 올라오는 엔티티 객체 dto로 변환처리
Hchanghyeon Jul 6, 2023
187cd8e
refactor: 생성자에서 만들던 UUID를 외부로 변경
Hchanghyeon Jul 6, 2023
95e8501
refactor: 생성자에 빌더 적용시키는 것으로 변경
Hchanghyeon Jul 6, 2023
a5afc12
refactor: 메소드 네이밍 동사형으로 변경 처리
Hchanghyeon Jul 6, 2023
6932ea4
refactor: 바우처 레파지토리 메소드 추가 및 테스트 코드 수정
Hchanghyeon Jul 6, 2023
8e3ce37
feat: JdbcTemplate을 이용하여 바우처 Repository 구현
Hchanghyeon Jul 7, 2023
ef13556
feat: 바우처 CRUD 관련 서비스 로직 구현
Hchanghyeon Jul 7, 2023
067d1a7
feat: 바우처 CRUD 관련 컨트롤러 기능 로직 구현
Hchanghyeon Jul 7, 2023
3d86778
feat: 바우처 CRUD View 구현
Hchanghyeon Jul 7, 2023
b74388d
test: Voucher CRUD 관련 서비스 테스트 구현
Hchanghyeon Jul 7, 2023
cffd8ee
docs: README FILE 과제 설명 2주차 추가
Hchanghyeon Jul 7, 2023
6eb4633
docs: 2주차 기능명세 및 구현사항 추가
Hchanghyeon Jul 7, 2023
f12e8e0
refactor: 생성자에서 만들던 UUID를 외부로 변경
Hchanghyeon Jul 6, 2023
bc5afc3
refactor: 바우처 레파지토리 메소드 추가 및 테스트 코드 수정
Hchanghyeon Jul 6, 2023
22b9fd0
feat: JdbcTemplate을 이용하여 바우처 Repository 구현
Hchanghyeon Jul 7, 2023
a2de8e3
feat: 바우처 CRUD 관련 서비스 로직 구현
Hchanghyeon Jul 7, 2023
06efeff
feat: 바우처 CRUD 관련 컨트롤러 기능 로직 구현
Hchanghyeon Jul 7, 2023
020a355
feat: 바우처 CRUD View 구현
Hchanghyeon Jul 7, 2023
80f67ef
test: Voucher CRUD 관련 서비스 테스트 구현
Hchanghyeon Jul 7, 2023
10d560b
docs: README FILE 과제 설명 2주차 추가
Hchanghyeon Jul 7, 2023
f5c5a21
docs: 2주차 기능명세 및 구현사항 추가
Hchanghyeon Jul 7, 2023
866297d
Merge branch 'w2-3' of https://github.com/Hchanghyeon/springboot-basi…
Hchanghyeon Jul 7, 2023
bbbaee9
refactor: 메소드 네이밍 동사형으로 변경
Hchanghyeon Jul 7, 2023
ad97318
refactor: 불필요 어노테이션 삭제, 불필요 파일 삭제
Hchanghyeon Jul 7, 2023
c448834
refactor: java17에서 개선된 toList()로 문법 변경
Hchanghyeon Jul 10, 2023
c0a59ae
refactor: 클래스 끝줄 개행 컨벤 적용
Hchanghyeon Jul 10, 2023
f4ae3f5
refactor: findById return값 Optinal로 처리 및 테스트 코드 수정
Hchanghyeon Jul 10, 2023
6ca5617
test: mockito를 활용한 고객 서비스 단위테스트
Hchanghyeon Jul 10, 2023
de8ee99
test: 고객 서비스 레이어 Mockito 테스트 추가
Hchanghyeon Jul 12, 2023
76bde6c
refactor: 네이밍 수정, NPE방지를 위해 isEmpty가 아닌 Collection Utils isEmpty로 처리
Hchanghyeon Jul 12, 2023
fe1eecf
refactor: 데이터가 없을 경우 빈 객체를 내리는 것으로 변경
Hchanghyeon Jul 12, 2023
410e4c2
refactor: voucherFactory에서 switch문법 개선
Hchanghyeon Jul 12, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839

.idea
file

# User-specific stuff
.idea/**/workspace.xml
Expand Down Expand Up @@ -169,4 +170,4 @@ gradle-app.setting
# Java heap dump
*.hprof

# End of https://www.toptal.com/developers/gitignore/api/java,intellij,gradle
# End of https://www.toptal.com/developers/gitignore/api/java,intellij,gradle
51 changes: 44 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,28 +1,65 @@
# SpringBoot Basic Weekly Mission

## 📌 과제 설명

### **바우처 관리 애플리케이션**

### 1주차 미션

- **기본**
- [x] SpringBoot CLI를 이용해서 프로젝트를 생성한다.
- [x] SpringBoot CLI를 이용해서 프로젝트를 생성한다.
- [x] CLI로 제작한다.
- [x] 스프링 부트 애플리케이션으로 만든다.
- [x] 프로그램이 시작하면 다음과 같이 지원 가능한 명령어를 알려준다.

``` shell
=== Voucher Program ===
Type exit to exit the program.
Type create to create a new voucher.
Type list to list all vouchers.
```

- [x] create, list 커맨드를 지원한다.
- [x] create 커맨드를 통해 바우처를 생성할 수 있다.(FixedAmountVoucher, PercentDiscountVoucher)
- [x] list 커맨드를 통해 만들어진 바우처를 조회할 수 있다.
- [x] 바우처 정보를 메모리에 관리한다.
- [x] create 커맨드를 통해 바우처를 생성할 수 있다.(FixedAmountVoucher, PercentDiscountVoucher)
- [x] list 커맨드를 통해 만들어진 바우처를 조회할 수 있다.
- [x] 바우처 정보를 메모리에 관리한다.
- [x] 적절한 로그를 기록하고 logback 설정을해서 에러는 파일로 기록된다.
- [x] 실행가능한 jar 파일을 생성한다.
- **심화**
- [x] 메모리 관리가 아닌 파일로 관리가 되는 Repository 생성
- [x] 기존 메모리 레파지토리는 지우지 말고 개발 프로파일에서만 동작하게 설정
- [x] 기존 메모리 레파지토리는 지우지 말고 개발 프로파일에서만 동작하게 설정
- [x] 고객 블랙 리스트 명단을 작성한다.
- [x] customer_blacklist.csv 파일을 만들고 스프링 애플리케이션에서 해당 파일을 읽을 수 있고 블랙 리스트를 조회 할 수 있다.
- [x] YAML 프로퍼티를 만들고 어떤 설정을 만들 수 있을지 고민해본다.
- [x] customer_blacklist.csv 파일을 만들고 스프링 애플리케이션에서 해당 파일을 읽을 수 있고 블랙 리스트를 조회 할 수 있다.
- [x] YAML 프로퍼티를 만들고 어떤 설정을 만들 수 있을지 고민해본다.

### 2주차 미션

**기본**

**2-1**

- [x] 바우처 관리 애플리케이션에 단위테스트를 작성해보세요.
- [x] 가능한 많은 단위 테스트코드를 작성하려고 노력해보세요.
- [x] 엣지 케이스(예외 케이스)를 고려해서 작성해주세요..

**2-2**

- [x] 바우처 관리 애플리케이션에서도 과정에서 다루었던 고객을 적용해보세요.
- [x] customers 테이블 정의 및 추가
- [x] CustomerRepository 추가 및 JdbcTemplate을 사용해서 구현

**2-3**

- [x] (1주차엔 파일로 관리하게 했다.) 바우처 정보를 DB로 관리해보세요.
- [x] 바우처에 엔터티에 해당하는 vouchers 테이블을 한번 정의해보세요.
- [x] 바우처 레포지토리를 만들어보세요. (JdbcTemplate을 사용해서 구현)
- [x] 기존의 파일에서 바우처를 관리한 것을 vouchers 테이블을 통해서 CRUD가 되게 해보세요.

**심화**

**2-4**

- [ ] 특정 고객에게 바우처를 할당할 수 있습니다.
- [ ] 고객이 어떤 바우처를 보유하고 있는지 조회할 수 있어야 합니다.
- [ ] 고객이 보유한 바우처를 제거할 수 있어야 합니다.
- [ ] 특정 바우처를 보유한 고객을 조회할 수 있어야 합니다.
27 changes: 15 additions & 12 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -1,31 +1,34 @@
plugins {
id 'java'
id 'org.springframework.boot' version '3.1.0'
id 'io.spring.dependency-management' version '1.1.0'
id 'java'
id 'org.springframework.boot' version '3.1.0'
id 'io.spring.dependency-management' version '1.1.0'
}

group = 'com.programmers'
version = '0.0.1-SNAPSHOT'

java {
sourceCompatibility = '17'
sourceCompatibility = '17'
}

repositories {
mavenCentral()
mavenCentral()
}

dependencies {
implementation 'org.springframework.boot:spring-boot-starter'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
implementation 'org.springframework.boot:spring-boot-starter'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
implementation 'org.springframework.boot:spring-boot-starter-jdbc'

compileOnly 'org.projectlombok:lombok:1.18.28'
annotationProcessor 'org.projectlombok:lombok:1.18.28'
runtimeOnly 'com.h2database:h2'

testCompileOnly 'org.projectlombok:lombok:1.18.28'
testAnnotationProcessor 'org.projectlombok:lombok:1.18.28'
compileOnly 'org.projectlombok:lombok:1.18.28'
annotationProcessor 'org.projectlombok:lombok:1.18.28'

testCompileOnly 'org.projectlombok:lombok:1.18.28'
testAnnotationProcessor 'org.projectlombok:lombok:1.18.28'
}

tasks.named('test') {
useJUnitPlatform()
useJUnitPlatform()
}
3 changes: 0 additions & 3 deletions file/customer_blacklist.csv

This file was deleted.

11 changes: 0 additions & 11 deletions file/voucher_list.csv

This file was deleted.

53 changes: 7 additions & 46 deletions src/main/java/com/programmers/springweekly/ConsoleApplication.java
Original file line number Diff line number Diff line change
@@ -1,26 +1,21 @@
package com.programmers.springweekly;

import com.programmers.springweekly.controller.CustomerController;
import com.programmers.springweekly.controller.VoucherController;
import com.programmers.springweekly.domain.ProgramMenu;
import com.programmers.springweekly.domain.customer.Customer;
import com.programmers.springweekly.domain.voucher.Voucher;
import com.programmers.springweekly.domain.voucher.VoucherType;
import com.programmers.springweekly.view.Console;
import java.util.Map;
import java.util.UUID;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.CommandLineRunner;
import org.springframework.context.annotation.Profile;
import org.springframework.stereotype.Component;

@Component
@RequiredArgsConstructor
@Slf4j
@Profile("!test")
public class ConsoleApplication implements CommandLineRunner {

private final CustomerController customerController;
private final VoucherController voucherController;
private final ConsoleVoucher consoleVoucher;
private final ConsoleCustomer consoleCustomer;
private final Console console;

private boolean running = true;
Expand All @@ -30,19 +25,17 @@ public void run(String... args) {
while (running) {
console.outputProgramGuide();
try {
ProgramMenu selectMenu = ProgramMenu.findProgramMenu(console.inputMessage());
ProgramMenu selectMenu = ProgramMenu.from(console.inputMessage());

switch (selectMenu) {
case CREATE -> createVoucher();
case LIST -> getVoucherList();
case CUSTOMER -> consoleCustomer.menu();
case VOUCHER -> consoleVoucher.menu();
case EXIT -> {
console.outputExitMessage();
running = false;
}
case BLACKLIST -> getBlackList();
default -> throw new IllegalArgumentException("Input :" + selectMenu + "The type you are looking for is not found.");
}

} catch (IllegalArgumentException e) {
log.error("잘못된 입력값 입니다 -> " + e.getMessage());
} catch (Exception e) {
Expand All @@ -51,36 +44,4 @@ public void run(String... args) {
}
}

private void createVoucher() {
console.outputSelectCreateVoucherGuide();
VoucherType voucherType = VoucherType.findVoucherMenu(console.inputMessage());

console.outputDiscountGuide();
String inputNumber = console.inputMessage();
log.info("user input: {} ", inputNumber);

voucherController.createVoucher(voucherType, inputNumber);
}

private void getVoucherList() {
Map<UUID, Voucher> voucherMap = voucherController.getVoucherList();

if (voucherMap.isEmpty()) {
console.outputErrorMessage("No vouchers saved");
return;
}

console.outputGetVoucherAll(voucherMap);
}

private void getBlackList() {
Map<UUID, Customer> customerMap = customerController.getBlackList();

if (customerMap.isEmpty()) {
console.outputErrorMessage("There are no saved blacklists.");
return;
}

console.outputGetCustomerBlackList(customerMap);
}
}
82 changes: 82 additions & 0 deletions src/main/java/com/programmers/springweekly/ConsoleCustomer.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package com.programmers.springweekly;

import com.programmers.springweekly.controller.CustomerController;
import com.programmers.springweekly.domain.CustomerMenu;
import com.programmers.springweekly.dto.customer.request.CustomerUpdateRequest;
import com.programmers.springweekly.dto.customer.response.CustomerListResponse;
import com.programmers.springweekly.view.Console;
import java.util.UUID;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

@Component
@RequiredArgsConstructor
public class ConsoleCustomer {

private final CustomerController customerController;
private final Console console;

public void menu() {
console.outputCustomerMenuGuide();
CustomerMenu customerMenu = CustomerMenu.from(console.inputMessage());

switch (customerMenu) {
case CREATE -> createCustomer();
case UPDATE -> updateCustomer();
case DELETE -> deleteCustomer();
case SELECT -> selectCustomer();
case BLACKLIST -> getBlackList();
default -> throw new IllegalArgumentException("Input :" + customerMenu + "찾으시는 고객 메뉴가 없습니다.");
}
}

private void selectCustomer() {
CustomerListResponse customerListResponse = customerController.findAll();

if (CollectionUtils.isEmpty(customerListResponse.getCustomerList())) {
console.outputErrorMessage("고객이 저장되어 있지 않습니다.");
return;
}

console.outputGetCustomerList(customerListResponse);
}

private void deleteCustomer() {
console.outputUUIDGuide();
UUID customerId = console.inputUUID();

customerController.deleteById(customerId);
console.outputCompleteGuide();
}

private void updateCustomer() {
console.outputUUIDGuide();
UUID customerId = console.inputUUID();

console.outputCustomerUpdateGuide();
CustomerUpdateRequest customerUpdateRequest = console.inputCustomerUpdate(customerId);

customerController.update(customerUpdateRequest);
console.outputCompleteGuide();
}

private void createCustomer() {
console.outputCustomerCreateGuide();

customerController.save(console.inputCustomerCreate());
console.outputCompleteGuide();
}

private void getBlackList() {
CustomerListResponse customerBlacklistResponse = customerController.getBlackList();

if (CollectionUtils.isEmpty(customerBlacklistResponse.getCustomerList())) {
console.outputErrorMessage("블랙 리스트인 고객이 없습니다.");
return;
}

console.outputGetCustomerList(customerBlacklistResponse);
}

}
Loading