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

[5기 - 이중원] SpringBoot Part3 Weekly Mission 제출합니다. #970

Open
wants to merge 74 commits into
base: shoeone
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
74 commits
Select commit Hold shift + click to select a range
2cfd990
chore: 로그설정 변경
shoeone96 Nov 1, 2023
ab537b1
build: thymeleaf 의존성 추가
shoeone96 Nov 1, 2023
143ea86
feat: voucher 받는 페이지 전송 컨트롤러 추가
shoeone96 Nov 1, 2023
f54ae10
refactor: voucherResponseDto record로 변환
shoeone96 Nov 1, 2023
50e516c
feat: 모든 voucher를 불러오는 기본 페이지 작성
shoeone96 Nov 1, 2023
f84a2ee
chore: docker 포트 변경
shoeone96 Nov 2, 2023
90d64ae
feat: voucherconsoler과 web 버전 분리
shoeone96 Nov 2, 2023
2f5e047
refactor: requestDto를 class -> record로 변경
shoeone96 Nov 2, 2023
888f096
chore: console로 진행하는 class 명 변경
shoeone96 Nov 2, 2023
b106396
chore: 스프링 구동 로그 제거
shoeone96 Nov 2, 2023
656ac05
feat: 새로운 voucher 페이지로 넘어가는 url 생성
shoeone96 Nov 2, 2023
e3f8c4d
feat: 새로운 voucher를 등록하는 api 생성
shoeone96 Nov 2, 2023
fdab3d6
feat: 새로운 voucher를 생성하는 페이지 작성
shoeone96 Nov 2, 2023
a06c20a
refactor: ui refactoring
shoeone96 Nov 2, 2023
a903890
chore: 사용하지 않는 import 문 제거
shoeone96 Nov 2, 2023
06b430c
chore: voucherService 메서드 명 변경
shoeone96 Nov 3, 2023
f0661d5
feat: voucher 상세페이지 조회 api 추가
shoeone96 Nov 3, 2023
0fa0927
refactor: voucherResponseDto로 변환하여 model 전달
shoeone96 Nov 3, 2023
9a3745e
feat: voucher 상세 조회 서비스 로직 작성
shoeone96 Nov 3, 2023
8c9d938
refactor: voucher id를 누르면 상세페이지 갈 수 있게 변경
shoeone96 Nov 3, 2023
c1b4fc7
feat: voucher 상세페이지 작성
shoeone96 Nov 3, 2023
acab01c
feat: voucher 삭제 api 추가
shoeone96 Nov 3, 2023
574c0b9
feat: voucher 상세페이지 삭제 기능
shoeone96 Nov 4, 2023
a690cd9
feat: voucher 삭제 api 추가
shoeone96 Nov 5, 2023
c47a0fd
refactor: double brace를 이용한 HashMap 초기화 부분 변경
shoeone96 Nov 5, 2023
351a4b2
feat: 이미 삭제되었거나 존재하지 않는 id의 voucher 검색 시 보여주는 페이지 작성
shoeone96 Nov 5, 2023
6289fe6
feat: customer 목록을 불러오는 페이지 api 작성
shoeone96 Nov 5, 2023
5aa2bf2
feat: customer 목록을 불러오는 서비스 로직 작성
shoeone96 Nov 5, 2023
d48a364
feat: customer 목록을 불러오는 페이지 작성, Customer 정보 페이지에 넣기 위한 getter 추가
shoeone96 Nov 5, 2023
b3223fd
feat: 새로운 고객 생성 페이지 이동 항목 추가
shoeone96 Nov 5, 2023
2a62343
chore: voucher 생성 시 로그 찍히는 부분 삭제
shoeone96 Nov 5, 2023
1f0a414
feat: 고객 생성 페이지 및 생성 api 추가
shoeone96 Nov 5, 2023
ad4ab58
feat: 고객 생성을 위한 dto record 추가
shoeone96 Nov 5, 2023
fbf567c
feat: 고객 생성 로직 추가
shoeone96 Nov 5, 2023
1df00a5
feat: 고객 생성 페이지 생성
shoeone96 Nov 5, 2023
52b3520
feat: customer 상세페이지 가져오기 api 작성
shoeone96 Nov 5, 2023
ac9547c
feat: 고객 상세페이지 가져오는 서비스 로직 추가
shoeone96 Nov 5, 2023
54a0120
feat: 고객을 지 못할 시 발생하는 errormessage 추가
shoeone96 Nov 5, 2023
f2259de
feat: 고객 상세페이지 및 고객 상세페이지 들어갈 수 있는 경로 추가
shoeone96 Nov 5, 2023
d5b64d8
refactor: 사용하지 않는 Model 인수 삭제
shoeone96 Nov 5, 2023
928a67e
feat: blacklist를 불러오는 페이지 api 추가
shoeone96 Nov 5, 2023
320a0f0
feat: black list 페이지 라우팅 추가
shoeone96 Nov 5, 2023
6ae254f
refactor: dto record -> class로 재 변경
shoeone96 Nov 5, 2023
f3adea9
feat: default home 화면 api, index.html 생성
shoeone96 Nov 5, 2023
e61363d
feat: voucher 사용자 할당 화면 및 할당 api 작성
shoeone96 Nov 5, 2023
9c51d76
feat: voucher 할당 ui 작성
shoeone96 Nov 5, 2023
55c86a4
refactor: nav 바 home 화면 추가
shoeone96 Nov 5, 2023
7621d23
Merge pull request #9 from shoeone96/week3
shoeone96 Nov 5, 2023
daa7ec1
feedback1: blacklist 찾아오는 test 추가
shoeone96 Nov 5, 2023
b5fc35c
feedback3: voucherType test case 추가
shoeone96 Nov 5, 2023
8ff277d
refactor: voucher 할당 페이지에서 voucherid 안보이는 부분 수정
shoeone96 Nov 5, 2023
a621efd
chore: 설명 추가
shoeone96 Nov 5, 2023
b062ff4
feat: restApi 방식의 컨트롤러 추가
shoeone96 Nov 6, 2023
da3092e
feat: RestApi 실행 시 일괄 반환할 class 생성
shoeone96 Nov 6, 2023
1e62ee8
refactor: profile 수정: 원하는 화면 전달방식에 따라 변경
shoeone96 Nov 6, 2023
107a963
refactor: reponse 값을 json으로 전달하기 위해 getter 전달
shoeone96 Nov 6, 2023
af88595
feat: Custom Exception 과 Enum을 이용해서 예외처리하는 방식 도입
shoeone96 Nov 6, 2023
be43468
feat: customer RestAPI 만들기
shoeone96 Nov 6, 2023
abf4e90
test: Custom Exception 도입에 따른 test 코드 수정
shoeone96 Nov 6, 2023
0846470
feat: Customer에 생성 시간과 수정 시간 추가
shoeone96 Nov 8, 2023
9a6c275
feat: Customer 도메인 model class에도 생성시간과 수정 시간 추가
shoeone96 Nov 8, 2023
9ace237
feat: voucher에 생성 시간 및 수정 시간 추가
shoeone96 Nov 8, 2023
f15bc48
chore: csv 파일 gitignore에 추가
shoeone96 Nov 8, 2023
20dd088
feat: requestParam 이 있는 경우 그 시간에 맞춰서 조회하는 rest API 메서드 추가
shoeone96 Nov 8, 2023
719fb6f
feat: 조회 시작 시간과 종료 시간을 포함해서 voucher를 조회하는 로직 추가
shoeone96 Nov 8, 2023
81c405f
feat: 조회 시작 시간과 종료 시간을 포함해서 voucher를 조회하는 jdbc로직 추가
shoeone96 Nov 8, 2023
0cee509
feat: fileRepository와 MemoryRepository에서 시간기한 별로 조회하는 메서드 추가
shoeone96 Nov 8, 2023
b46dce4
chore: naming convention 지키기
shoeone96 Nov 9, 2023
efe9095
feat: voucher 등록 시 필요한 validation 작성
shoeone96 Nov 9, 2023
a335184
feat: voucher 등록 시 발생할 수 있는 enum 작성
shoeone96 Nov 9, 2023
ecdea71
feat: voucher 등록 시 타입이 잘못 기록된 경우 처리해줄 수 있는 예외 처리
shoeone96 Nov 9, 2023
9b2e795
test: voucher 등록 시 발생하는 예외 테스트
shoeone96 Nov 9, 2023
a232c8a
refactor: VouchergiveRequestDto -> record변경 및 notnull 유효성 검증 추가
shoeone96 Nov 9, 2023
1e27ba4
feat: customer 등록 시 nonnull 조건 추가
shoeone96 Nov 9, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
.idea/**/dictionaries
.idea/**/shelf

**/csv/**

# AWS User-specific
.idea/**/aws.xml

Expand Down
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,13 @@
스프링부트 basic 위클리미션을 코드리뷰하는 Repository입니다.

주차별 과제는 데브코스 노션에서 확인하세요!


### 사용방법
1. pull 받는다.
2. docker를 띄운다.
3. `docker build -t mysql-image .`
4. `docker run -dit --name mysql-container -p 3300:3306 mysql-image`
5. docker 올라온 것을 확인 후 프로젝트 실행

기존 3000포트 -> 3300포트로 변경(react 충돌)
3 changes: 1 addition & 2 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,9 @@ repositories {
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-jdbc'
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf:3.1.5'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
implementation 'com.mysql:mysql-connector-j:8.1.0'
// https://mvnrepository.com/artifact/com.wix/wix-embedded-mysql
testImplementation 'com.wix:wix-embedded-mysql:4.6.1'
}

tasks.named('test') {
Expand Down
8 changes: 8 additions & 0 deletions mysql/init.sql
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ CREATE TABLE customers (
customer_id BINARY(16),
customer_name VARCHAR(30),
customer_type VARCHAR(30),
created_at datetime(6) not null ,

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
created_at datetime(6) not null ,
created_at datetime(6) NOT NULL,

통일성을 맞춰서 예약어는 대문자로 쓰시는게 어떨까요?

updated_at datetime(6) DEFAULT null,
CONSTRAINT customer_pk PRIMARY KEY(customer_id)
);

Expand All @@ -14,6 +16,8 @@ CREATE TABLE vouchers (
discount_value BIGINT,
voucher_type VARCHAR(30),
customer_id BINARY(16),
created_at datetime(6) not null ,
updated_at datetime(6) DEFAULT null,
CONSTRAINT voucher_pk PRIMARY KEY(voucher_id),
CONSTRAINT voucher_fk FOREIGN KEY (customer_id) REFERENCES customers (customer_id)
);
Expand All @@ -26,6 +30,8 @@ CREATE TABLE customers (
customer_id BINARY(16),
customer_name VARCHAR(30),
customer_type VARCHAR(30),
created_at datetime(6) not null ,
updated_at datetime(6) DEFAULT null,
CONSTRAINT customer_pk PRIMARY KEY(customer_id)
);

Expand All @@ -34,6 +40,8 @@ CREATE TABLE vouchers (
discount_value BIGINT,
voucher_type VARCHAR(30),
customer_id BINARY(16),
created_at datetime(6) not null ,
updated_at datetime(6) DEFAULT null,
CONSTRAINT voucher_pk PRIMARY KEY(voucher_id),
CONSTRAINT voucher_fk FOREIGN KEY (customer_id) REFERENCES customers (customer_id)
);
12 changes: 12 additions & 0 deletions src/main/java/org/programmers/springorder/HomeController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package org.programmers.springorder;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;

@Controller
public class HomeController {
@GetMapping("/")
public String home(){
return "index";
}
}
Original file line number Diff line number Diff line change
@@ -1,17 +1,21 @@
package org.programmers.springorder;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.util.List;

@SpringBootApplication
public class SpringOrderApplication {
private static final Logger log = LoggerFactory.getLogger(SpringOrderApplication.class);
public class SpringOrderApplication implements WebMvcConfigurer {

public static void main(String[] args) {
log.info("Voucher 관리 애플리케이션 구동");
SpringApplication.run(SpringOrderApplication.class, args).close();
}
public static void main(String[] args) {
SpringApplication.run(SpringOrderApplication.class, args);
}

@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
WebMvcConfigurer.super.configureMessageConverters(converters);
}
}
39 changes: 29 additions & 10 deletions src/main/java/org/programmers/springorder/VoucherApplication.java
Original file line number Diff line number Diff line change
@@ -1,46 +1,65 @@
package org.programmers.springorder;

import org.programmers.springorder.console.Console;
import org.programmers.springorder.consts.ErrorMessage;
import org.programmers.springorder.consts.Message;
import org.programmers.springorder.customer.controller.CustomerController;
import org.programmers.springorder.utils.MenuType;
import org.programmers.springorder.voucher.controller.VoucherController;
import org.programmers.springorder.voucher.controller.VoucherConsoleController;
import org.springframework.boot.CommandLineRunner;
import org.springframework.context.annotation.Profile;
import org.springframework.stereotype.Component;

@Profile("test")
@Component
public class VoucherApplication implements CommandLineRunner {

private final Console console;
private final VoucherController voucherController;
private final VoucherConsoleController voucherConsoleController;
private final CustomerController customerController;
public VoucherApplication(Console console, VoucherController voucherController, CustomerController customerController) {
public VoucherApplication(Console console, VoucherConsoleController voucherConsoleController, CustomerController customerController) {
this.console = console;
this.voucherController = voucherController;
this.voucherConsoleController = voucherConsoleController;
this.customerController = customerController;
}

@Override
public void run(String... args) {
boolean isRunning = true;

boolean isRunning = true;
boolean isWeb = false;
if(chooseMedia()){
isWeb = true;
};
while(isRunning) {
if(isWeb) break;
MenuType menu = console.inputMenu();

switch (menu) {
case EXIT -> {
isRunning = false;
console.printMessage(Message.EXIT_PROGRAM_MESSAGE);
}
case CREATE -> voucherController.createVoucher();
case LIST -> voucherController.getVoucherList();
case CREATE -> voucherConsoleController.createVoucher();
case LIST -> voucherConsoleController.getVoucherList();
case BLACK -> customerController.printBlackList();
case ALLOCATE -> voucherController.giveVoucher();
case GET_OWNER_VOUCHER -> voucherController.getVouchersOfOwner();
case DELETE_VOUCHER -> voucherController.deleteVoucher();
case ALLOCATE -> voucherConsoleController.giveVoucher();
case GET_OWNER_VOUCHER -> voucherConsoleController.getVouchersOfOwner();
case DELETE_VOUCHER -> voucherConsoleController.deleteVoucher();
case SEARCH_VOUCHER_OWNER -> customerController.getVoucherOwner();
}
}
}

private boolean chooseMedia() {
String media = console.chooseMedia();
if(media.equals("1")){
return true;
}
if(media.equals("2")){
return false;
};
throw new RuntimeException(ErrorMessage.INVALID_VALUE_MESSAGE);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@

import java.util.InputMismatchException;
import java.util.List;
import java.util.Optional;
import java.util.UUID;

@Component
Expand Down Expand Up @@ -122,4 +121,9 @@ public UUID getVoucherId() {
public void showCustomer(CustomerResponseDto customer) {
printMessage(customer.toString());
}

public String chooseMedia() {
printMessage(Message.CHOOSING_MEDIA);
return input.getInput();
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package org.programmers.springorder.console;

import org.programmers.springorder.utils.Validation;

import java.util.Scanner;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ public class ErrorMessage {

private ErrorMessage(){}

public static final String CUSTOMER_NOT_FOUND = "등록된 회원이 존재하지 않습니다.";

public static final String VOUCHER_NOT_EXIST_MESSAGE = "등록된 바우처가 존재하지 않습니다.";

public static final String EMPTY_VALUE_MESSAGE = "값이 존재하지 않습니다. 다시 입력해주세요.";
Expand Down
6 changes: 6 additions & 0 deletions src/main/java/org/programmers/springorder/consts/Message.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@

public class Message {

public static final String CHOOSING_MEDIA = """
어떤 방식으로 구동하시겠습니까?
1. web 방식
2. console 방식
""";

private Message(){}
public static final String MENU_SELECT_MESSAGE = """
=== Voucher Program ===
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@

import org.programmers.springorder.console.Console;
import org.programmers.springorder.customer.service.CustomerService;
import org.springframework.context.annotation.Profile;
import org.springframework.stereotype.Controller;

import java.util.UUID;

@Profile("test")
@Controller
public class CustomerController {
private final Console console;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package org.programmers.springorder.customer.controller;

import org.programmers.springorder.customer.dto.CustomerRequestDto;
import org.programmers.springorder.customer.dto.CustomerResponseDto;
import org.programmers.springorder.customer.service.CustomerService;
import org.programmers.springorder.voucher.dto.VoucherResponseDto;
import org.programmers.springorder.voucher.service.VoucherService;
import org.springframework.context.annotation.Profile;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;

import java.util.List;
import java.util.UUID;

@Profile("prod")
@Controller
public class CustomerPageController {

private final CustomerService customerService;
private final VoucherService voucherService;

public CustomerPageController(CustomerService customerService, VoucherService voucherService) {
this.customerService = customerService;
this.voucherService = voucherService;
}

@GetMapping("/customers")

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/customers를 prefix 형태로 설정하면 좋을 것 같습니다.

public String getCustomerListPage(Model model){

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

query String으로 필터해서 blackcustomers까지 하나의 컨트롤러에서 처리하는게 훨씬 좋을거 같습니다.

List<CustomerResponseDto> allCustomers = customerService.getAllCustomers();
model.addAttribute("customerList", allCustomers);
return "customers";
}

@GetMapping("/blackCustomers")

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/customer path에 query string으로 표현해보는 건 어떨까요?

public String getBlackCustomerListPage(Model model){
List<CustomerResponseDto> allCustomers = customerService.getBlackList();
model.addAttribute("customerList", allCustomers);
return "customers";
}

@GetMapping("/customers/{customerId}")
public String getCustomerListPage(@PathVariable UUID customerId, Model model){
CustomerResponseDto customer = customerService.findCustomer(customerId);
List<VoucherResponseDto> customerOwnedVouchers = voucherService.getCustomerOwnedVouchers(customerId);
model.addAttribute("customer", customer);
model.addAttribute("customerVoucherList", customerOwnedVouchers);
return "customer-detail";
}

@GetMapping("/new-customer")
public String getNewCustomerPage(){
return "new-customer";
}
Comment on lines +53 to +56

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
@GetMapping("/new-customer")
public String getNewCustomerPage(){
return "new-customer";
}
@GetMapping("/customers/new")
public String getNewCustomerPage(){
return "new-customer";
}


@PostMapping("/customers")
public String enrollCustomer(CustomerRequestDto requestDto){
customerService.newCustomer(requestDto);
return "redirect:/customers";
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package org.programmers.springorder.customer.controller;

import org.programmers.springorder.customer.dto.CustomerRequestDto;
import org.programmers.springorder.customer.dto.CustomerResponseDto;
import org.programmers.springorder.customer.service.CustomerService;
import org.programmers.springorder.voucher.dto.Response;
import org.springframework.context.annotation.Profile;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;
import java.util.UUID;

@Profile("default")
@RestController
public class CustomerRestController {

private final CustomerService customerService;

public CustomerRestController(CustomerService customerService) {
this.customerService = customerService;
}

@GetMapping("api/v1/customers")

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ReqeustMapping에 api/v1/customers를 동일하게 넣어두면 좋을거 같습니다.

public Response<List<CustomerResponseDto>> getCustomerListPage(){

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

blackcustomers를 쿼리스토링으로 필터링 하는게 더 좋을거 같아요.

return Response.success(customerService.getAllCustomers());
}

@GetMapping("api/v1/blackCustomers")
public Response<List<CustomerResponseDto>> getBlackCustomerListPage(){
return Response.success(customerService.getBlackList());
}

@GetMapping("api/v1/customers/{customerId}")
public Response<CustomerResponseDto> getCustomerDetail(@PathVariable UUID customerId, Model model){
return Response.success(customerService.findCustomer(customerId));
}


@PostMapping("api/v1/customers")
public Response<Void> enrollCustomer(CustomerRequestDto requestDto){
customerService.newCustomer(requestDto);
return Response.success();

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

status 204 no_content 을 쓰는게 더 좋을거 같습니다.

}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package org.programmers.springorder.customer.dto;

import org.programmers.springorder.customer.model.CustomerType;
import org.springframework.lang.NonNull;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

validatiton으로 하면 좋을거 같습니다.


public record CustomerRequestDto(
@NonNull String name,
@NonNull CustomerType customerType) {
Comment on lines +7 to +8

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

빈값이 들어와도 괜찮을까요?

}
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,14 @@ public UUID getCustomerId() {
return customerId;
}

public String getName() {
return name;
}

public String getCustomerType() {
return customerType;
}

@Override
public String toString() {
return "customerId : " + customerId +'\n' +
Expand Down