From 7494782546bfd09f14f61c31df420796bd591d6d Mon Sep 17 00:00:00 2001 From: ASak1104 Date: Mon, 30 Oct 2023 22:56:01 +0900 Subject: [PATCH 01/73] =?UTF-8?q?fix=20:=20ddl=20wallet=20=ED=85=8C?= =?UTF-8?q?=EC=9D=B4=EB=B8=94=EC=97=90=20cascade=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/resources/schema.sql | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/resources/schema.sql b/src/main/resources/schema.sql index 63e5f37948..1dba33a4f1 100644 --- a/src/main/resources/schema.sql +++ b/src/main/resources/schema.sql @@ -19,7 +19,7 @@ create table wallet ( customer_id BINARY(16) NOT NULL, voucher_id BINARY(16) NOT NULL, - FOREIGN KEY (customer_id) REFERENCES customer(id), - FOREIGN KEY (voucher_id) REFERENCES voucher(id), + FOREIGN KEY (customer_id) REFERENCES customer(id) ON DELETE CASCADE, + FOREIGN KEY (voucher_id) REFERENCES voucher(id) ON DELETE CASCADE, PRIMARY KEY (customer_id, voucher_id) ); From 080148d138f327cc906a831a5ee10107f4b57c08 Mon Sep 17 00:00:00 2001 From: ASak1104 Date: Mon, 30 Oct 2023 22:56:41 +0900 Subject: [PATCH 02/73] =?UTF-8?q?refactor=20:=20Jdbc=20=EB=B9=88=20?= =?UTF-8?q?=EC=84=A4=EC=A0=95=EA=B3=BC=20repository=20=EB=B9=88=20?= =?UTF-8?q?=EC=84=A4=EC=A0=95=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../configuration/TestJdbcConfiguration.java | 6 ----- .../TestJdbcRepositoryConfiguration.java | 22 +++++++++++++++++++ .../repository/JdbcVoucherRepositoryTest.java | 9 ++++---- 3 files changed, 26 insertions(+), 11 deletions(-) create mode 100644 src/test/java/team/marco/voucher_management_system/configuration/TestJdbcRepositoryConfiguration.java diff --git a/src/test/java/team/marco/voucher_management_system/configuration/TestJdbcConfiguration.java b/src/test/java/team/marco/voucher_management_system/configuration/TestJdbcConfiguration.java index cd62b2e5bb..3e8e7afc82 100644 --- a/src/test/java/team/marco/voucher_management_system/configuration/TestJdbcConfiguration.java +++ b/src/test/java/team/marco/voucher_management_system/configuration/TestJdbcConfiguration.java @@ -7,7 +7,6 @@ import org.springframework.context.annotation.Bean; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; -import team.marco.voucher_management_system.repository.JdbcVoucherRepository; @TestConfiguration public class TestJdbcConfiguration { @@ -31,9 +30,4 @@ public JdbcTemplate jdbcTemplate(DataSource dataSource) { public NamedParameterJdbcTemplate namedParameterJdbcTemplate(DataSource dataSource) { return new NamedParameterJdbcTemplate(dataSource); } - - @Bean - public JdbcVoucherRepository jdbcVoucherRepository(NamedParameterJdbcTemplate namedParameterJdbcTemplate) { - return new JdbcVoucherRepository(namedParameterJdbcTemplate); - } } diff --git a/src/test/java/team/marco/voucher_management_system/configuration/TestJdbcRepositoryConfiguration.java b/src/test/java/team/marco/voucher_management_system/configuration/TestJdbcRepositoryConfiguration.java new file mode 100644 index 0000000000..a333c9698f --- /dev/null +++ b/src/test/java/team/marco/voucher_management_system/configuration/TestJdbcRepositoryConfiguration.java @@ -0,0 +1,22 @@ +package team.marco.voucher_management_system.configuration; + +import org.springframework.boot.test.context.TestConfiguration; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; +import team.marco.voucher_management_system.repository.JdbcCustomerRepository; +import team.marco.voucher_management_system.repository.JdbcVoucherRepository; + +@TestConfiguration +@ComponentScan(basePackageClasses = TestJdbcConfiguration.class) +public class TestJdbcRepositoryConfiguration { + @Bean + public JdbcVoucherRepository jdbcVoucherRepository(NamedParameterJdbcTemplate jdbcTemplate) { + return new JdbcVoucherRepository(jdbcTemplate); + } + + @Bean + public JdbcCustomerRepository jdbcCustomerRepository(NamedParameterJdbcTemplate jdbcTemplate) { + return new JdbcCustomerRepository(jdbcTemplate); + } +} diff --git a/src/test/java/team/marco/voucher_management_system/repository/JdbcVoucherRepositoryTest.java b/src/test/java/team/marco/voucher_management_system/repository/JdbcVoucherRepositoryTest.java index e7b3104817..c233f4de1b 100644 --- a/src/test/java/team/marco/voucher_management_system/repository/JdbcVoucherRepositoryTest.java +++ b/src/test/java/team/marco/voucher_management_system/repository/JdbcVoucherRepositoryTest.java @@ -6,13 +6,12 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; -import team.marco.voucher_management_system.configuration.TestJdbcConfiguration; -import team.marco.voucher_management_system.configuration.TestPropertyConfiguration; +import team.marco.voucher_management_system.configuration.TestJdbcRepositoryConfiguration; @TestInstance(TestInstance.Lifecycle.PER_CLASS) -@SpringJUnitConfig({TestPropertyConfiguration.class, TestJdbcConfiguration.class}) +@SpringJUnitConfig(TestJdbcRepositoryConfiguration.class) class JdbcVoucherRepositoryTest extends VoucherRepositoryTest { - private static final String TRUNCATE_SQL = "DELETE FROM voucher;"; + private static final String DELETE_FROM_VOUCHER = "DELETE FROM voucher;"; @Autowired private JdbcTemplate jdbcTemplate; @@ -27,6 +26,6 @@ protected VoucherRepository getRepository() { @BeforeAll @AfterEach void truncateTable() { - jdbcTemplate.execute(TRUNCATE_SQL); + jdbcTemplate.execute(DELETE_FROM_VOUCHER); } } From ed2c696877ff5cafd11e1d50c3638761ba20c237 Mon Sep 17 00:00:00 2001 From: ASak1104 Date: Mon, 30 Oct 2023 23:42:07 +0900 Subject: [PATCH 03/73] =?UTF-8?q?test=20:=20=EC=A1=B0=ED=9A=8C=ED=95=9C=20?= =?UTF-8?q?Voucher=20=EC=A0=95=EB=B3=B4=EB=A5=BC=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=ED=95=A0=20=EB=95=8C=20=EC=88=9C=EC=84=9C=EA=B0=80=20?= =?UTF-8?q?=EC=83=81=EA=B4=80=20=EC=97=86=EB=8F=84=EB=A1=9D=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../repository/VoucherRepositoryTest.java | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/test/java/team/marco/voucher_management_system/repository/VoucherRepositoryTest.java b/src/test/java/team/marco/voucher_management_system/repository/VoucherRepositoryTest.java index d8358b5861..757bf4face 100644 --- a/src/test/java/team/marco/voucher_management_system/repository/VoucherRepositoryTest.java +++ b/src/test/java/team/marco/voucher_management_system/repository/VoucherRepositoryTest.java @@ -6,8 +6,8 @@ import static org.hamcrest.Matchers.notNullValue; import java.util.ArrayList; -import java.util.Comparator; import java.util.List; +import java.util.UUID; import org.assertj.core.api.Assertions; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -34,7 +34,7 @@ void testNonNullRepository() { } @Test - @DisplayName("Voucher 추가가 가능해야한다.") + @DisplayName("Voucher 추가가 가능해야 한다.") void testSave() { // given VoucherRepository repository = getRepository(); @@ -47,7 +47,7 @@ void testSave() { } @Test - @DisplayName("추가한 모든 Voucher를 조회할 수 있어야한다.") + @DisplayName("추가한 모든 Voucher를 조회할 수 있어야 한다.") void testFindAll() { // given VoucherRepository repository = getRepository(); @@ -57,20 +57,20 @@ void testFindAll() { generatedVouchers.add(generateVoucher()); } - generatedVouchers.sort(Comparator.comparing(Voucher::getId)); - // when generatedVouchers.forEach(repository::save); // then - List retrievedVouchers = repository.findAll() + List generatedIds = generatedVouchers.stream() + .map(Voucher::getId) + .toList(); + List retrievedIds = repository.findAll() .stream() - .sorted(Comparator.comparing(Voucher::getId)) + .map(Voucher::getId) .toList(); - assertThat(retrievedVouchers, not(empty())); + assertThat(retrievedIds, not(empty())); - Assertions.assertThat(retrievedVouchers).usingRecursiveComparison() - .isEqualTo(generatedVouchers); + Assertions.assertThat(retrievedIds).containsExactlyInAnyOrderElementsOf(generatedIds); } } From c8a2b1c17c8ffdb3110ff10f2e1c7d86ae14cc10 Mon Sep 17 00:00:00 2001 From: ASak1104 Date: Mon, 30 Oct 2023 23:52:39 +0900 Subject: [PATCH 04/73] =?UTF-8?q?test=20:=20save=20=EB=A9=94=EC=84=9C?= =?UTF-8?q?=EB=93=9C=20=ED=85=8C=EC=8A=A4=ED=8A=B8=EC=97=90=20=EB=8C=80?= =?UTF-8?q?=ED=95=9C=20=EA=B2=80=EC=A6=9D=20=EB=B6=80=EB=B6=84=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../repository/VoucherRepositoryTest.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/test/java/team/marco/voucher_management_system/repository/VoucherRepositoryTest.java b/src/test/java/team/marco/voucher_management_system/repository/VoucherRepositoryTest.java index 757bf4face..0f25d46efd 100644 --- a/src/test/java/team/marco/voucher_management_system/repository/VoucherRepositoryTest.java +++ b/src/test/java/team/marco/voucher_management_system/repository/VoucherRepositoryTest.java @@ -1,5 +1,6 @@ package team.marco.voucher_management_system.repository; +import static org.assertj.core.api.Assertions.assertThatNoException; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.empty; import static org.hamcrest.Matchers.not; @@ -9,6 +10,7 @@ import java.util.List; import java.util.UUID; import org.assertj.core.api.Assertions; +import org.assertj.core.api.ThrowableAssert.ThrowingCallable; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import team.marco.voucher_management_system.model.FixedAmountVoucher; @@ -41,9 +43,10 @@ void testSave() { Voucher voucher = generateVoucher(); // when - repository.save(voucher); + ThrowingCallable targetMethod = () -> repository.save(voucher); // then + assertThatNoException().isThrownBy(targetMethod); } @Test From 9d617ab969a5b96c20f3e950e9bc55ecf2935ae9 Mon Sep 17 00:00:00 2001 From: ASak1104 Date: Tue, 31 Oct 2023 00:03:25 +0900 Subject: [PATCH 05/73] =?UTF-8?q?test=20:=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=EC=98=88=EC=99=B8=EC=97=90=20=EB=8C=80=ED=95=9C=20=EA=B2=80?= =?UTF-8?q?=EC=A6=9D=20=EB=B6=80=EB=B6=84=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../model/Customer.java | 2 +- .../model/CustomerTest.java | 49 +++++++++++++------ 2 files changed, 36 insertions(+), 15 deletions(-) diff --git a/src/main/java/team/marco/voucher_management_system/model/Customer.java b/src/main/java/team/marco/voucher_management_system/model/Customer.java index 3328e42a9f..80165717b7 100644 --- a/src/main/java/team/marco/voucher_management_system/model/Customer.java +++ b/src/main/java/team/marco/voucher_management_system/model/Customer.java @@ -82,7 +82,7 @@ private void validateName(String name) { private void validateEmail(String email) { if (!Pattern.matches(EMAIL_REGEX, email)) { - throw new IllegalArgumentException("이메일 형식이 올바르지 않습니다.."); + throw new IllegalArgumentException("이메일 형식이 올바르지 않습니다."); } } diff --git a/src/test/java/team/marco/voucher_management_system/model/CustomerTest.java b/src/test/java/team/marco/voucher_management_system/model/CustomerTest.java index f7eba36bde..e7ccfcf2dc 100644 --- a/src/test/java/team/marco/voucher_management_system/model/CustomerTest.java +++ b/src/test/java/team/marco/voucher_management_system/model/CustomerTest.java @@ -1,17 +1,21 @@ package team.marco.voucher_management_system.model; +import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; +import static org.assertj.core.api.Assertions.assertThatNoException; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.not; import static org.hamcrest.Matchers.notNullValue; -import static org.junit.jupiter.api.Assertions.assertThrows; import java.time.LocalDateTime; +import org.assertj.core.api.ThrowableAssert.ThrowingCallable; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; class CustomerTest { + private static final String INVALID_NAME_MESSAGE = "이름은 공백일 수 없습니다."; + private static final String INVALID_EMAIL_MESSAGE = "이메일 형식이 올바르지 않습니다."; private Customer generateCustomer() { return new Customer("test", "test@test.test"); @@ -21,26 +25,31 @@ private Customer generateCustomer() { @DisplayName("고객 생성 이름 테스트") class TestCreationName { @Test - @DisplayName("이름이 빈 문자열이 아니면 생성에 성공해야한다.") + @DisplayName("이름이 빈 문자열이 아니면 생성에 성공해야 한다.") void success() { // given String name = "test"; String email = "test@test.test"; // when + ThrowingCallable targetMethod = () -> new Customer(name, email); + // then - new Customer(name, email); + assertThatNoException().isThrownBy(targetMethod); } @Test - @DisplayName("이름이 빈 문자열이면 생성에 실패해야한다.") + @DisplayName("이름이 빈 문자열이면 생성에 실패해야 한다.") void fail() { String name = ""; String email = "test@test.test"; // when + ThrowingCallable targetMethod = () -> new Customer(name, email); + // then - assertThrows(IllegalArgumentException.class, () -> new Customer(name, email)); + assertThatIllegalArgumentException().isThrownBy(targetMethod) + .withMessage(INVALID_NAME_MESSAGE); } } @@ -48,26 +57,31 @@ void fail() { @DisplayName("고객 생성 이메일 테스트") class TestCreationEmail { @Test - @DisplayName("이메일이 형식에 맞으면 생성에 성공해야한다.") + @DisplayName("이메일이 형식에 맞으면 생성에 성공해야 한다.") void success() { // given String name = "test"; String email = "test@test.test"; // when + ThrowingCallable targetMethod = () -> new Customer(name, email); + // then - new Customer(name, email); + assertThatNoException().isThrownBy(targetMethod); } @Test - @DisplayName("이메일이 형식에 맞지 않으면 생성에 실패해야한다.") + @DisplayName("이메일이 형식에 맞지 않으면 생성에 실패해야 한다.") void fail() { String name = "test"; String email = "test"; // when + ThrowingCallable targetMethod = () -> new Customer(name, email); + // then - assertThrows(IllegalArgumentException.class, () -> new Customer(name, email)); + assertThatIllegalArgumentException().isThrownBy(targetMethod) + .withMessage(INVALID_EMAIL_MESSAGE); } } @@ -75,31 +89,38 @@ void fail() { @DisplayName("고객 이름 변경 테스트") class TestChangeName { @Test - @DisplayName("이름이 빈 문자열이 아니면 변경에 성공해야한다.") + @DisplayName("이름이 빈 문자열이 아니면 변경에 성공해야 한다.") void success() { // given Customer customer = generateCustomer(); String name = "test2"; // when - // then customer.changeName(name); + + // then + String customerName = customer.getName(); + + assertThat(customerName, is(name)); } @Test - @DisplayName("이름이 빈 문자열이면 변경에 실패해야한다.") + @DisplayName("이름이 빈 문자열이면 변경에 실패해야 한다.") void fail() { Customer customer = generateCustomer(); String name = ""; // when + ThrowingCallable targetMethod = () -> customer.changeName(name); + // then - assertThrows(IllegalArgumentException.class, () -> customer.changeName(name)); + assertThatIllegalArgumentException().isThrownBy(targetMethod) + .withMessage(INVALID_NAME_MESSAGE); } } @Test - @DisplayName("로그인을 하면 lastLoginAt 필드 값이 바뀌어야한다.") + @DisplayName("로그인을 하면 lastLoginAt 필드 값이 바뀌어야 한다.") void testLogin() { // given Customer customer = generateCustomer(); From 408969dc417f43deb8d6662b9b955dc2e436fa03 Mon Sep 17 00:00:00 2001 From: ASak1104 Date: Tue, 31 Oct 2023 00:12:22 +0900 Subject: [PATCH 06/73] =?UTF-8?q?test=20:=20=EB=B8=94=EB=9E=99=EB=A6=AC?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=EC=9C=A0=EC=A0=80=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EA=B0=95=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../model/BlacklistUserTest.java | 35 ++++++++++++++++--- 1 file changed, 30 insertions(+), 5 deletions(-) diff --git a/src/test/java/team/marco/voucher_management_system/model/BlacklistUserTest.java b/src/test/java/team/marco/voucher_management_system/model/BlacklistUserTest.java index 7f5fec2d21..3f97920310 100644 --- a/src/test/java/team/marco/voucher_management_system/model/BlacklistUserTest.java +++ b/src/test/java/team/marco/voucher_management_system/model/BlacklistUserTest.java @@ -1,32 +1,57 @@ package team.marco.voucher_management_system.model; -import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; +import static org.assertj.core.api.Assertions.assertThatNoException; +import static org.hamcrest.MatcherAssert.assertThat; import java.util.UUID; +import org.assertj.core.api.ThrowableAssert.ThrowingCallable; +import org.hamcrest.Matchers; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; class BlacklistUserTest { @Test @DisplayName("이름이 빈 문자열이 아니면 생성에 성공해야한다.") - void successCreation() { + void testSuccessCreation() { // given UUID id = UUID.randomUUID(); String name = "test"; // when + ThrowingCallable targetMethod = () -> new BlacklistUser(id, name); + // then - new BlacklistUser(id, name); + assertThatNoException().isThrownBy(targetMethod); } @Test @DisplayName("이름이 빈 문자열이면 생성에 실패해야한다.") - void failCreation() { + void testFailCreation() { UUID id = UUID.randomUUID(); String name = ""; // when + ThrowingCallable targetMethod = () -> new BlacklistUser(id, name); + // then - assertThrows(IllegalArgumentException.class, () -> new BlacklistUser(id, name)); + assertThatIllegalArgumentException().isThrownBy(targetMethod) + .withMessage("이름은 빈 문자열 일 수 없습니다."); + } + + @Test + @DisplayName("블랙리스트 사용자의 정보에는 id와 이름이 포함되어야 한다.") + void testGetInfo() { + UUID id = UUID.randomUUID(); + String name = "smith"; + + // when + BlacklistUser blacklistUser = new BlacklistUser(id, name); + + // then + String blacklistUserInfo = blacklistUser.getInfo(); + + assertThat(blacklistUserInfo, Matchers.containsString(id.toString())); + assertThat(blacklistUserInfo, Matchers.containsString(name)); } } From c0ef95aafdd7a4093505a17689944840404d564e Mon Sep 17 00:00:00 2001 From: ASak1104 Date: Tue, 31 Oct 2023 00:48:24 +0900 Subject: [PATCH 07/73] =?UTF-8?q?test=20:=20Voucher=20=EB=AA=A8=EB=8D=B8?= =?UTF-8?q?=EC=97=90=20=EB=8C=80=ED=95=9C=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=EA=B0=95=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../model/FixedAmountVoucherTest.java | 42 +++++++++--- .../model/PercentDiscountVoucherTest.java | 48 ++++++++++---- .../model/VoucherTest.java | 64 +++++++++++++++++++ 3 files changed, 132 insertions(+), 22 deletions(-) create mode 100644 src/test/java/team/marco/voucher_management_system/model/VoucherTest.java diff --git a/src/test/java/team/marco/voucher_management_system/model/FixedAmountVoucherTest.java b/src/test/java/team/marco/voucher_management_system/model/FixedAmountVoucherTest.java index f867d0d61a..7be949f533 100644 --- a/src/test/java/team/marco/voucher_management_system/model/FixedAmountVoucherTest.java +++ b/src/test/java/team/marco/voucher_management_system/model/FixedAmountVoucherTest.java @@ -1,25 +1,37 @@ package team.marco.voucher_management_system.model; +import static java.text.MessageFormat.format; +import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.greaterThanOrEqualTo; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.lessThanOrEqualTo; -import static org.junit.jupiter.api.Assertions.assertThrows; +import org.assertj.core.api.ThrowableAssert.ThrowingCallable; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import team.marco.voucher_management_system.type_enum.VoucherType; -class FixedAmountVoucherTest { +class FixedAmountVoucherTest extends VoucherTest { private static final VoucherType FIXED_VOUCHER_TYPE = VoucherType.FIXED; private static final int MAXIMUM_AMOUNT = (int) 1e9; private static final int MINIMUM_AMOUNT = 1; + @Override + protected int generateValidData() { + return (MAXIMUM_AMOUNT + MINIMUM_AMOUNT) / 2; + } + + @Override + protected Voucher generateVoucher(int data) { + return new FixedAmountVoucher(data); + } + @Test - @DisplayName("올바른 파라미터를 넘겼을 때 바우처가 생성되야한다.") + @DisplayName("올바른 파라미터를 넘겼을 때 바우처가 생성되야 한다.") void testCreation() { // given - int amount = 10_000; + int amount = generateValidData(); // when FixedAmountVoucher fixedAmountVoucher = new FixedAmountVoucher(amount); @@ -33,7 +45,7 @@ void testCreation() { } @Test - @DisplayName("생성 시 최소 할인 금액 보다 작을 경우 오류를 발생시켜야한다.") + @DisplayName("생성 시 최소 할인 금액 보다 작을 경우 오류를 발생 시켜야 한다.") void testCreationLessThanMinimumAmount() { // given int lessThanMinimumAmount = MINIMUM_AMOUNT - 1; @@ -41,13 +53,18 @@ void testCreationLessThanMinimumAmount() { assertThat(lessThanMinimumAmount, greaterThanOrEqualTo(Integer.MIN_VALUE)); // when + ThrowingCallable targetMethod = () -> new FixedAmountVoucher(lessThanMinimumAmount); + // then - assertThrows(IllegalArgumentException.class, - () -> new FixedAmountVoucher(lessThanMinimumAmount)); + String expectedMessage = format("{0}: 할인 금액은 {1} 보다 작을 수 없습니다.", + lessThanMinimumAmount, MINIMUM_AMOUNT); + + assertThatIllegalArgumentException().isThrownBy(targetMethod) + .withMessage(expectedMessage); } @Test - @DisplayName("생성 시 최소 할인 금액 보다 작을 경우 오류를 발생시켜야한다.") + @DisplayName("생성 시 최대 할인 금액 보다 클 경우 오류를 발생 시켜야 한다.") void testCreationGreaterThanMaximumAmount() { // given int greaterThanMaximumAmount = MAXIMUM_AMOUNT + 1; @@ -55,8 +72,13 @@ void testCreationGreaterThanMaximumAmount() { assertThat(greaterThanMaximumAmount, lessThanOrEqualTo(Integer.MAX_VALUE)); // when + ThrowingCallable targetMethod = () -> new FixedAmountVoucher(greaterThanMaximumAmount); + // then - assertThrows(IllegalArgumentException.class, - () -> new FixedAmountVoucher(greaterThanMaximumAmount)); + String expectedMessage = format("{0}: 할인 금액은 {1} 보다 클 수 없습니다.", + greaterThanMaximumAmount, MAXIMUM_AMOUNT); + + assertThatIllegalArgumentException().isThrownBy(targetMethod) + .withMessage(expectedMessage); } } diff --git a/src/test/java/team/marco/voucher_management_system/model/PercentDiscountVoucherTest.java b/src/test/java/team/marco/voucher_management_system/model/PercentDiscountVoucherTest.java index 35f6bfa1ac..f0b94ac462 100644 --- a/src/test/java/team/marco/voucher_management_system/model/PercentDiscountVoucherTest.java +++ b/src/test/java/team/marco/voucher_management_system/model/PercentDiscountVoucherTest.java @@ -1,25 +1,37 @@ package team.marco.voucher_management_system.model; +import static java.text.MessageFormat.format; +import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.greaterThanOrEqualTo; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.lessThanOrEqualTo; -import static org.junit.jupiter.api.Assertions.assertThrows; +import org.assertj.core.api.ThrowableAssert.ThrowingCallable; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import team.marco.voucher_management_system.type_enum.VoucherType; -class PercentDiscountVoucherTest { +class PercentDiscountVoucherTest extends VoucherTest { private static final VoucherType PERCENT_VOUCHER_TYPE = VoucherType.PERCENT; private static final int MAXIMUM_PERCENT = 100; private static final int MINIMUM_PERCENT = 1; + @Override + protected int generateValidData() { + return (MAXIMUM_PERCENT + MINIMUM_PERCENT) / 2; + } + + @Override + protected Voucher generateVoucher(int data) { + return new PercentDiscountVoucher(data); + } + @Test - @DisplayName("올바른 파라미터를 넘겼을 때 바우처가 생성되야한다.") + @DisplayName("올바른 파라미터를 넘겼을 때 바우처가 생성되야 한다.") void testCreation() { // given - int percent = 50; + int percent = generateValidData(); // when PercentDiscountVoucher percentDiscountVoucher = new PercentDiscountVoucher(percent); @@ -33,7 +45,7 @@ void testCreation() { } @Test - @DisplayName("생성 시 최소 할인 퍼센트 보다 작을 경우 오류를 발생시켜야한다.") + @DisplayName("생성 시 최소 할인 퍼센트 보다 작을 경우 오류를 발생 시켜야 한다.") void testCreationLessThanMinimumPercent() { // given int lessThanMinimumPercent = MINIMUM_PERCENT - 1; @@ -41,13 +53,19 @@ void testCreationLessThanMinimumPercent() { assertThat(lessThanMinimumPercent, greaterThanOrEqualTo(Integer.MIN_VALUE)); // when - // then - assertThrows(IllegalArgumentException.class, - () -> new PercentDiscountVoucher(lessThanMinimumPercent)); + ThrowingCallable targetMethod = () -> new PercentDiscountVoucher(lessThanMinimumPercent); + + // + String expectedMessage = format("{0}: 할인율은 {1}% 보다 작을 수 없습니다.", + lessThanMinimumPercent, MINIMUM_PERCENT); + + // when + assertThatIllegalArgumentException().isThrownBy(targetMethod) + .withMessage(expectedMessage); } @Test - @DisplayName("생성 시 최대 할인 퍼센트 보다 클 경우 오류를 발생시켜야한다.") + @DisplayName("생성 시 최대 할인 퍼센트 보다 클 경우 오류를 발생 시켜야 한다.") void testCreationGreaterThanMaximumPercent() { // given int greaterThanMaximumPercent = MAXIMUM_PERCENT + 1; @@ -55,8 +73,14 @@ void testCreationGreaterThanMaximumPercent() { assertThat(greaterThanMaximumPercent, lessThanOrEqualTo(Integer.MAX_VALUE)); // when - // then - assertThrows(IllegalArgumentException.class, - () -> new PercentDiscountVoucher(greaterThanMaximumPercent)); + ThrowingCallable targetMethod = () -> new PercentDiscountVoucher(greaterThanMaximumPercent); + + // + String expectedMessage = format("{0}: 할인율은 {1}%를 초과할 수 없습니다.", + greaterThanMaximumPercent, MAXIMUM_PERCENT); + + // when + assertThatIllegalArgumentException().isThrownBy(targetMethod) + .withMessage(expectedMessage); } } diff --git a/src/test/java/team/marco/voucher_management_system/model/VoucherTest.java b/src/test/java/team/marco/voucher_management_system/model/VoucherTest.java new file mode 100644 index 0000000000..689998179a --- /dev/null +++ b/src/test/java/team/marco/voucher_management_system/model/VoucherTest.java @@ -0,0 +1,64 @@ +package team.marco.voucher_management_system.model; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.instanceOf; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.notNullValue; + +import java.text.NumberFormat; +import java.util.UUID; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import team.marco.voucher_management_system.type_enum.VoucherType; + +abstract class VoucherTest { + abstract protected int generateValidData(); + + abstract protected Voucher generateVoucher(int data); + + @Test + @DisplayName("쿠폰의 타입은 null일 수 없고 VoucherType에 정의되야 한다.") + void testGetType() { + // given + Voucher voucher = generateVoucher(generateValidData()); + + // when + VoucherType voucherType = voucher.getType(); + + // then + assertThat(voucherType, notNullValue()); + assertThat(voucherType, instanceOf(VoucherType.class)); + } + + @Test + @DisplayName("쿠폰 생성 시 주어진 data와 동일한 쿠폰이 생성되야 한다.") + void testGetData() { + // given + int initData = generateValidData(); + Voucher voucher = generateVoucher(initData); + + // when + int voucherData = voucher.getData(); + + // then + assertThat(voucherData, is(initData)); + } + + @Test + @DisplayName("쿠폰 정보에는 ID 정보와 주어진 data의 콤마 포맷 정보가 포함되야 한다.") + void testGetInfo() { + // given + int initData = generateValidData(); + Voucher voucher = generateVoucher(initData); + + // when + String voucherInfo = voucher.getInfo(); + + // then + UUID id = voucher.getId(); + + assertThat(voucherInfo, containsString(id.toString())); + assertThat(voucherInfo, containsString(NumberFormat.getIntegerInstance().format(initData))); + } +} From 5fda05f53703ad30713d6737f9b7ec3641782ccf Mon Sep 17 00:00:00 2001 From: ASak1104 Date: Tue, 31 Oct 2023 01:54:55 +0900 Subject: [PATCH 08/73] =?UTF-8?q?fix=20:=20=EB=8D=B0=EC=9D=B4=ED=84=B0?= =?UTF-8?q?=EB=B2=A0=EC=9D=B4=EC=8A=A4=20=EC=BB=A4=EB=84=A5=EC=85=98?= =?UTF-8?q?=EC=9D=B4=20=EC=97=86=EC=9D=84=20=EB=95=8C=EC=9D=98=20=EB=B2=84?= =?UTF-8?q?=EA=B7=B8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/CommandCustomerApplication.java | 12 ++++++++---- .../application/CommandMainApplication.java | 15 +++++++++++---- .../application/CommandWalletApplication.java | 4 ---- .../service/CustomerService.java | 6 +++--- 4 files changed, 22 insertions(+), 15 deletions(-) diff --git a/src/main/java/team/marco/voucher_management_system/application/CommandCustomerApplication.java b/src/main/java/team/marco/voucher_management_system/application/CommandCustomerApplication.java index 01eb9cf0b5..5de2f9e7bf 100644 --- a/src/main/java/team/marco/voucher_management_system/application/CommandCustomerApplication.java +++ b/src/main/java/team/marco/voucher_management_system/application/CommandCustomerApplication.java @@ -3,8 +3,9 @@ import java.util.NoSuchElementException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.dao.DataAccessResourceFailureException; +import org.springframework.dao.DuplicateKeyException; import org.springframework.dao.EmptyResultDataAccessException; +import org.springframework.jdbc.datasource.lookup.DataSourceLookupFailureException; import org.springframework.stereotype.Component; import team.marco.voucher_management_system.controller.ConsoleCustomerController; import team.marco.voucher_management_system.type_enum.CustomerCommandType; @@ -48,12 +49,15 @@ private void executeCommand(int userInput) { } catch (IllegalArgumentException e) { logger.warn(e.toString()); Console.print(e.getMessage()); + } catch (DataSourceLookupFailureException e) { + logger.error(e.toString()); + Console.print(e.getMessage()); + } catch (DuplicateKeyException e) { + logger.error(e.toString()); + Console.print("이미 존재하는 이메일 입니다."); } catch (EmptyResultDataAccessException | NoSuchElementException e) { logger.error(e.toString()); Console.print("존재하지 않는 ID 입니다."); - } catch (DataAccessResourceFailureException e) { - logger.error(e.toString()); - Console.print(e.getMessage()); } } diff --git a/src/main/java/team/marco/voucher_management_system/application/CommandMainApplication.java b/src/main/java/team/marco/voucher_management_system/application/CommandMainApplication.java index 8b7175b37f..2dc11726b3 100644 --- a/src/main/java/team/marco/voucher_management_system/application/CommandMainApplication.java +++ b/src/main/java/team/marco/voucher_management_system/application/CommandMainApplication.java @@ -2,6 +2,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.jdbc.CannotGetJdbcConnectionException; import org.springframework.stereotype.Component; import team.marco.voucher_management_system.controller.ConsoleBlacklistController; import team.marco.voucher_management_system.controller.ConsoleVoucherController; @@ -31,11 +32,10 @@ public CommandMainApplication(ConsoleVoucherController voucherController, protected void start() { try { selectCommand(); + } catch (CannotGetJdbcConnectionException e) { + errorHandler(e, "데이터베이스에 연결할 수 없습니다."); } catch (Exception e) { - logger.error(e.toString()); - Console.print("프로그램에 에러가 발생했습니다."); - - runningFlag = false; + errorHandler(e, "프로그램에 에러가 발생했습니다."); } } @@ -79,6 +79,13 @@ private void switchCommand(MainCommandType commandType) { } } + private void errorHandler(Exception e, String message) { + logger.error(e.toString()); + Console.print(message); + + runningFlag = false; + } + @Override protected void close() { Console.print("프로그램이 종료되었습니다."); diff --git a/src/main/java/team/marco/voucher_management_system/application/CommandWalletApplication.java b/src/main/java/team/marco/voucher_management_system/application/CommandWalletApplication.java index 1ccb1ace47..ab92e8c2d1 100644 --- a/src/main/java/team/marco/voucher_management_system/application/CommandWalletApplication.java +++ b/src/main/java/team/marco/voucher_management_system/application/CommandWalletApplication.java @@ -3,7 +3,6 @@ import java.util.NoSuchElementException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.dao.DataAccessResourceFailureException; import org.springframework.dao.DuplicateKeyException; import org.springframework.dao.EmptyResultDataAccessException; import org.springframework.jdbc.UncategorizedSQLException; @@ -48,9 +47,6 @@ private void executeCommand(int userInput) { } catch (IllegalArgumentException e) { logger.warn(e.toString()); Console.print(e.getMessage()); - } catch (DataAccessResourceFailureException e) { - logger.error(e.toString()); - Console.print(e.getMessage()); } catch (DuplicateKeyException e) { logger.error(e.toString()); Console.print("이미 존재하는 쿠폰입니다."); diff --git a/src/main/java/team/marco/voucher_management_system/service/CustomerService.java b/src/main/java/team/marco/voucher_management_system/service/CustomerService.java index c1e48984d6..3a3a0669bb 100644 --- a/src/main/java/team/marco/voucher_management_system/service/CustomerService.java +++ b/src/main/java/team/marco/voucher_management_system/service/CustomerService.java @@ -2,7 +2,7 @@ import java.util.List; import java.util.Optional; -import org.springframework.dao.DataAccessResourceFailureException; +import org.springframework.jdbc.datasource.lookup.DataSourceLookupFailureException; import org.springframework.stereotype.Service; import team.marco.voucher_management_system.model.Customer; import team.marco.voucher_management_system.repository.JdbcCustomerRepository; @@ -21,7 +21,7 @@ public void create(String name, String email) { int insert = customerRepository.create(customer); if (insert != 1) { - throw new DataAccessResourceFailureException("고객을 추가하는 과정에서 오류가 발생했습니다."); + throw new DataSourceLookupFailureException("고객을 추가하는 과정에서 오류가 발생했습니다."); } } @@ -39,7 +39,7 @@ public void update(String id, String name) { int update = customerRepository.update(customer); if (update != 1) { - throw new DataAccessResourceFailureException("고객을 추가하는 과정에서 오류가 발생했습니다."); + throw new DataSourceLookupFailureException("고객을 추가하는 과정에서 오류가 발생했습니다."); } } From 1b029d4bba46470278835fb19eb1ffd58a399a02 Mon Sep 17 00:00:00 2001 From: ASak1104 Date: Tue, 31 Oct 2023 02:46:48 +0900 Subject: [PATCH 09/73] =?UTF-8?q?fix=20:=20=EC=A1=B4=EC=9E=AC=ED=95=98?= =?UTF-8?q?=EC=A7=80=20=EC=95=8A=EB=8A=94=20=EA=B3=A0=EA=B0=9D=EC=9D=84=20?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C=ED=95=A0=20=EB=95=8C=20=EB=B9=88=20Optional?= =?UTF-8?q?=20=EA=B0=9D=EC=B2=B4=EB=A5=BC=20=EB=B0=98=ED=99=98=ED=95=98?= =?UTF-8?q?=EB=8F=84=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../CommandCustomerApplication.java | 3 +-- .../repository/JdbcCustomerRepository.java | 21 ++++++++++++------- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/src/main/java/team/marco/voucher_management_system/application/CommandCustomerApplication.java b/src/main/java/team/marco/voucher_management_system/application/CommandCustomerApplication.java index 5de2f9e7bf..7a8f87813e 100644 --- a/src/main/java/team/marco/voucher_management_system/application/CommandCustomerApplication.java +++ b/src/main/java/team/marco/voucher_management_system/application/CommandCustomerApplication.java @@ -4,7 +4,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.dao.DuplicateKeyException; -import org.springframework.dao.EmptyResultDataAccessException; import org.springframework.jdbc.datasource.lookup.DataSourceLookupFailureException; import org.springframework.stereotype.Component; import team.marco.voucher_management_system.controller.ConsoleCustomerController; @@ -55,7 +54,7 @@ private void executeCommand(int userInput) { } catch (DuplicateKeyException e) { logger.error(e.toString()); Console.print("이미 존재하는 이메일 입니다."); - } catch (EmptyResultDataAccessException | NoSuchElementException e) { + } catch (NoSuchElementException e) { logger.error(e.toString()); Console.print("존재하지 않는 ID 입니다."); } diff --git a/src/main/java/team/marco/voucher_management_system/repository/JdbcCustomerRepository.java b/src/main/java/team/marco/voucher_management_system/repository/JdbcCustomerRepository.java index 8b6cf7b023..3c426f392b 100644 --- a/src/main/java/team/marco/voucher_management_system/repository/JdbcCustomerRepository.java +++ b/src/main/java/team/marco/voucher_management_system/repository/JdbcCustomerRepository.java @@ -12,6 +12,7 @@ import java.util.Objects; import java.util.Optional; import java.util.UUID; +import org.springframework.dao.EmptyResultDataAccessException; import org.springframework.jdbc.core.RowMapper; import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; import org.springframework.stereotype.Repository; @@ -60,20 +61,24 @@ public List findAll() { @Override public int update(Customer customer) { return jdbcTemplate.update( - "UPDATE customer SET name = :name, email = :email, last_login_at = :lastLoginAt" + "UPDATE customer SET name = :name, last_login_at = :lastLoginAt" + " WHERE id = UUID_TO_BIN(:id)", customerToMap(customer)); } @Override public Optional findById(String id) { - Customer customer = jdbcTemplate.queryForObject( - "SELECT * FROM customer" - + " WHERE id = UUID_TO_BIN(:id)", - Collections.singletonMap("id", id.getBytes()), - customerRowMapper); - - return Optional.ofNullable(customer); + try { + Customer customer = jdbcTemplate.queryForObject( + "SELECT * FROM customer" + + " WHERE id = UUID_TO_BIN(:id)", + Collections.singletonMap("id", id.getBytes()), + customerRowMapper); + + return Optional.ofNullable(customer); + } catch (EmptyResultDataAccessException e) { + return Optional.empty(); + } } @Override From 0c3f516aecdbc9b38b8394ff23ab1d5ec9631e87 Mon Sep 17 00:00:00 2001 From: ASak1104 Date: Tue, 31 Oct 2023 02:47:08 +0900 Subject: [PATCH 10/73] =?UTF-8?q?test=20:=20JdbcCustomerRepository=20test?= =?UTF-8?q?=20=EC=BD=94=EB=93=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../JdbcCustomerRepositoryTest.java | 229 ++++++++++++++++++ 1 file changed, 229 insertions(+) create mode 100644 src/test/java/team/marco/voucher_management_system/repository/JdbcCustomerRepositoryTest.java diff --git a/src/test/java/team/marco/voucher_management_system/repository/JdbcCustomerRepositoryTest.java b/src/test/java/team/marco/voucher_management_system/repository/JdbcCustomerRepositoryTest.java new file mode 100644 index 0000000000..a3bac98d27 --- /dev/null +++ b/src/test/java/team/marco/voucher_management_system/repository/JdbcCustomerRepositoryTest.java @@ -0,0 +1,229 @@ +package team.marco.voucher_management_system.repository; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import java.util.UUID; +import org.assertj.core.api.ThrowableAssert.ThrowingCallable; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.dao.DuplicateKeyException; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; +import team.marco.voucher_management_system.configuration.TestJdbcRepositoryConfiguration; +import team.marco.voucher_management_system.model.Customer; + +@TestInstance(TestInstance.Lifecycle.PER_CLASS) +@SpringJUnitConfig(TestJdbcRepositoryConfiguration.class) +class JdbcCustomerRepositoryTest { + private static final String DELETE_FROM_CUSTOMER = "DELETE FROM customer"; + + @Autowired + private JdbcTemplate jdbcTemplate; + @Autowired + private JdbcCustomerRepository repository; + + @BeforeAll + @AfterEach + void truncateTable() { + jdbcTemplate.execute(DELETE_FROM_CUSTOMER); + } + + @Nested + @DisplayName("고객 추가 테스트") + class TestCreate { + @Test + @DisplayName("고객을 추가할 수 있어야 한다.") + void success() { + // given + Customer customer = generateCustomer(1000); + + // when + int count = repository.create(customer); + + // then + assertThat(count).isEqualTo(1); + } + + @Test + @DisplayName("동일한 이메일의 고객을 추가할 경우 예외가 발생한다.") + void failToDuplicateEmail() { + // given + Customer customer = new Customer("test1", "test@test.test"); + Customer duplicatedEmailCustomer = new Customer("test2", "test@test.test"); + + // when + int initInsertion = repository.create(customer); + + ThrowingCallable targetMethod = () -> repository.create(duplicatedEmailCustomer); + + // then + assertThat(initInsertion).isEqualTo(1); + assertThatExceptionOfType(DuplicateKeyException.class).isThrownBy(targetMethod); + } + } + + @Test + @DisplayName("추가한 사용자를 모두 찾을 수 있어야 한다.") + void testFindAll() { + // given + int count = 33; + List generatedCustomers = addTestCustomers(count); + + // when + List customers = repository.findAll(); + + // then + assertThat(customers.size()).isEqualTo(count); + + List retrievedIds = customers.stream() + .map(Customer::getId) + .toList(); + List generatedIds = generatedCustomers.stream() + .map(Customer::getId) + .toList(); + + assertThat(retrievedIds).containsExactlyInAnyOrderElementsOf(generatedIds); + } + + @Test + @DisplayName("사용자의 이름을 수정할 수 있어야 한다.") + void testUpdate() { + // given + Customer generatedCustomer = generateCustomer(0); + String name = "changedName"; + + repository.create(generatedCustomer); + + // when + generatedCustomer.changeName(name); + repository.update(generatedCustomer); + + // then + Optional optionalCustomer = repository.findById(generatedCustomer.getId().toString()); + + assertThat(optionalCustomer.isPresent()).isTrue(); + + Customer customer = optionalCustomer.get(); + + assertThat(customer.getName()).isEqualTo(generatedCustomer.getName()); + assertThat(customer.getName()).isEqualTo(name); + } + + @Nested + @DisplayName("고객 id 조회 테스트") + class TestFindById { + @Test + @DisplayName("id가 일치하는 고객이 존재할 경우 조회할 수 있어야 한다.") + void success() { + // given + int seed = 100; + Customer existCustomer = generateCustomer(seed + 1); + Customer notExistCustomer = generateCustomer(seed + 2); + + addTestCustomers(seed); + repository.create(existCustomer); + + // when + Optional existOptionalCustomer = repository.findById(existCustomer.getId().toString()); + + // then + assertThat(existOptionalCustomer.isPresent()).isTrue(); + + Customer retrievedCustomer = existOptionalCustomer.get(); + + assertThat(retrievedCustomer).usingRecursiveComparison() + .isEqualTo(existCustomer); + } + + @Test + @DisplayName("id가 일치하는 고객이 없을 경우 예외를 발생해야 한다.") + void failToNotExistId() { + // given + int seed = 100; + Customer notExistCustomer = generateCustomer(seed + 1); + + addTestCustomers(seed); + + // when + Optional existOptionalCustomer = repository.findById(notExistCustomer.getId().toString()); + + // then + assertThat(existOptionalCustomer.isEmpty()).isTrue(); + } + } + + @Test + @DisplayName("특정 문자를 포함하는 이름의 사용자를 모두 조회할 수 있어야 한다.") + void testFindByName() { + // given + int seed = 100; + String queryName = "5"; + List addedCustomers = addTestCustomers(seed); + + // when + List customers = repository.findByName(queryName); + + // then + List addedIds = addedCustomers.stream() + .filter(customer -> customer.getName().contains(queryName)) + .map(Customer::getId) + .toList(); + List customerIds = customers.stream() + .map(Customer::getId) + .toList(); + + assertThat(customerIds).containsExactlyInAnyOrderElementsOf(addedIds); + } + + @Test + @DisplayName("특정 문자를 포함하는 이메일의 사용자를 모두 조회할 수 있어야 한다.") + void testFindByEmail() { + // given + int seed = 100; + String queryEmail = "st5"; + List addedCustomers = addTestCustomers(seed); + + // when + List customers = repository.findByEmail(queryEmail); + + // then + List addedIds = addedCustomers.stream() + .filter(customer -> customer.getEmail().contains(queryEmail)) + .map(Customer::getId) + .toList(); + List customerIds = customers.stream() + .map(Customer::getId) + .toList(); + + assertThat(customerIds).containsExactlyInAnyOrderElementsOf(addedIds); + } + + private Customer generateCustomer(int seed) { + String name = String.format("testUser%d", seed); + String email = String.format("test%d@test.test", seed); + + return new Customer(name, email); + } + + private List addTestCustomers(int count) { + List generatedCustomers = new ArrayList<>(); + + for (int i = 0; i < count; i++) { + Customer customer = generateCustomer(i); + + repository.create(customer); + generatedCustomers.add(customer); + } + + return generatedCustomers.stream().toList(); + } +} From 555b8156f324133f7da55242e700634a0acf5d7d Mon Sep 17 00:00:00 2001 From: ASak1104 Date: Tue, 31 Oct 2023 03:49:15 +0900 Subject: [PATCH 11/73] =?UTF-8?q?test=20:=20JdbcWalletRepository=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=BD=94=EB=93=9C=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/resources/schema.sql | 4 +- .../TestJdbcRepositoryConfiguration.java | 6 + .../repository/JdbcWalletRepositoryTest.java | 203 ++++++++++++++++++ 3 files changed, 211 insertions(+), 2 deletions(-) create mode 100644 src/test/java/team/marco/voucher_management_system/repository/JdbcWalletRepositoryTest.java diff --git a/src/main/resources/schema.sql b/src/main/resources/schema.sql index 1dba33a4f1..63e5f37948 100644 --- a/src/main/resources/schema.sql +++ b/src/main/resources/schema.sql @@ -19,7 +19,7 @@ create table wallet ( customer_id BINARY(16) NOT NULL, voucher_id BINARY(16) NOT NULL, - FOREIGN KEY (customer_id) REFERENCES customer(id) ON DELETE CASCADE, - FOREIGN KEY (voucher_id) REFERENCES voucher(id) ON DELETE CASCADE, + FOREIGN KEY (customer_id) REFERENCES customer(id), + FOREIGN KEY (voucher_id) REFERENCES voucher(id), PRIMARY KEY (customer_id, voucher_id) ); diff --git a/src/test/java/team/marco/voucher_management_system/configuration/TestJdbcRepositoryConfiguration.java b/src/test/java/team/marco/voucher_management_system/configuration/TestJdbcRepositoryConfiguration.java index a333c9698f..ef048790f9 100644 --- a/src/test/java/team/marco/voucher_management_system/configuration/TestJdbcRepositoryConfiguration.java +++ b/src/test/java/team/marco/voucher_management_system/configuration/TestJdbcRepositoryConfiguration.java @@ -6,6 +6,7 @@ import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; import team.marco.voucher_management_system.repository.JdbcCustomerRepository; import team.marco.voucher_management_system.repository.JdbcVoucherRepository; +import team.marco.voucher_management_system.repository.JdbcWalletRepository; @TestConfiguration @ComponentScan(basePackageClasses = TestJdbcConfiguration.class) @@ -19,4 +20,9 @@ public JdbcVoucherRepository jdbcVoucherRepository(NamedParameterJdbcTemplate jd public JdbcCustomerRepository jdbcCustomerRepository(NamedParameterJdbcTemplate jdbcTemplate) { return new JdbcCustomerRepository(jdbcTemplate); } + + @Bean + public JdbcWalletRepository jdbcWalletRepository(NamedParameterJdbcTemplate jdbcTemplate) { + return new JdbcWalletRepository(jdbcTemplate); + } } diff --git a/src/test/java/team/marco/voucher_management_system/repository/JdbcWalletRepositoryTest.java b/src/test/java/team/marco/voucher_management_system/repository/JdbcWalletRepositoryTest.java new file mode 100644 index 0000000000..d1e2c128cf --- /dev/null +++ b/src/test/java/team/marco/voucher_management_system/repository/JdbcWalletRepositoryTest.java @@ -0,0 +1,203 @@ +package team.marco.voucher_management_system.repository; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; +import org.assertj.core.api.ThrowableAssert.ThrowingCallable; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.dao.DataIntegrityViolationException; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; +import team.marco.voucher_management_system.configuration.TestJdbcRepositoryConfiguration; +import team.marco.voucher_management_system.model.Customer; +import team.marco.voucher_management_system.model.FixedAmountVoucher; +import team.marco.voucher_management_system.model.Voucher; + +@TestInstance(TestInstance.Lifecycle.PER_CLASS) +@SpringJUnitConfig(TestJdbcRepositoryConfiguration.class) +class JdbcWalletRepositoryTest { + private static final String DELETE_FROM_WALLET = "DELETE FROM wallet"; + private static final String DELETE_FROM_VOUCHER = "DELETE FROM voucher"; + private static final String DELETE_FROM_CUSTOMER = "DELETE FROM customer"; + + @Autowired + private JdbcTemplate jdbcTemplate; + @Autowired + private JdbcWalletRepository walletRepository; + @Autowired + private JdbcVoucherRepository voucherRepository; + @Autowired + private JdbcCustomerRepository customerRepository; + + @BeforeAll + void validateReferenceRepository() { + // To test wallet repository, implement jdbc and customer repository + truncateTables(); + + validate(voucherRepository); + validate(customerRepository); + + truncateTables(); + } + + @AfterEach + void truncateTables() { + jdbcTemplate.execute(DELETE_FROM_WALLET); + jdbcTemplate.execute(DELETE_FROM_VOUCHER); + jdbcTemplate.execute(DELETE_FROM_CUSTOMER); + } + + @Nested + @DisplayName("고객 지갑 쿠폰 추가 테스트") + class TestLink { + @Test + @DisplayName("고객의 지갑에 쿠폰을 추가할 수 있다.") + void success() { + // given + Voucher voucher = addVoucher(); + Customer customer = addCustomer(0); + + // when + int count = walletRepository.link(customer.getId().toString(), voucher.getId().toString()); + + // then + assertThat(count).isEqualTo(1); + } + + @Test + @DisplayName("이미 추가된 쿠폰은 지갑에 추가될 수 없다.") + void failToAlreadyExist() { + // given + Voucher voucher = addVoucher(); + Customer customer = addCustomer(0); + + walletRepository.link(customer.getId().toString(), voucher.getId().toString()); + + // when + ThrowingCallable targetMethod = () -> walletRepository.link( + customer.getId().toString(), voucher.getId().toString()); + + // then + assertThatExceptionOfType(DataIntegrityViolationException.class) + .isThrownBy(targetMethod); + } + } + + @Nested + @DisplayName("고객 지갑 쿠폰 반납 테스트") + class TestUnlink { + @Test + @DisplayName("고객의 지갑에 쿠폰을 반납할 수 있다.") + void success() { + // given + Voucher voucher = addVoucher(); + Customer customer = addCustomer(0); + + walletRepository.link(customer.getId().toString(), voucher.getId().toString()); + + // when + int count = walletRepository.unlink(customer.getId().toString(), voucher.getId().toString()); + + // then + assertThat(count).isEqualTo(1); + } + + @Test + @DisplayName("지갑에 없는 쿠폰은 지갑에 반납될 수 없다.") + void failToNotExist() { + // given + Voucher voucher = addVoucher(); + Customer customer = addCustomer(0); + + // when + int count = walletRepository.unlink(customer.getId().toString(), voucher.getId().toString()); + + // then + assertThat(count).isEqualTo(0); + } + } + + @Test + @DisplayName("특정 고객 지갑에 있는 모든 쿠폰을 조회할 수 있다.") + void getVoucherIds() { + // given + UUID customerId = addCustomer(0).getId(); + List voucherIds = List.of(addVoucher().getId(), addVoucher().getId(), addVoucher().getId()); + + voucherIds.forEach(voucherId -> walletRepository.link(customerId.toString(), voucherId.toString())); + + // when + List retrievedIds = walletRepository.getVoucherIds(customerId.toString()); + + // then + assertThat(retrievedIds).containsExactlyInAnyOrderElementsOf(voucherIds); + } + + @Test + @DisplayName("특정 쿠폰을 보유한 모든 사용자를 조회할 수 있다.") + void getCustomerIds() { + // given + UUID voucherId = addVoucher().getId(); + List customerIds = new ArrayList<>(); + + for (int i = 0; i < 5; i++) { + UUID customerId = addCustomer(i).getId(); + + customerIds.add(customerId); + walletRepository.link(customerId.toString(), voucherId.toString()); + } + + // when + List retrievedIds = walletRepository.getCustomerIds(voucherId.toString()); + + // then + assertThat(retrievedIds).containsExactlyInAnyOrderElementsOf(customerIds); + } + + private void validate(VoucherRepository voucherRepository) { + Voucher voucher = addVoucher(); + + List voucherIds = voucherRepository.findAll() + .stream() + .map(Voucher::getId) + .toList(); + + assert voucherIds.contains(voucher.getId()); + } + + private void validate(CustomerRepository customerRepository) { + Customer customer = addCustomer(0); + + List customerIds = customerRepository.findAll() + .stream() + .map(Customer::getId) + .toList(); + + assert customerIds.contains(customer.getId()); + } + + private Voucher addVoucher() { + Voucher voucher = new FixedAmountVoucher(100); + + voucherRepository.save(voucher); + + return voucher; + } + + private Customer addCustomer(int seed) { + Customer customer = new Customer("test", "test%d@test".formatted(seed)); + + customerRepository.create(customer); + + return customer; + } +} From 40e001abc00f74ec4e6e13397a1650e0409d4a57 Mon Sep 17 00:00:00 2001 From: ASak1104 Date: Sun, 5 Nov 2023 14:01:09 +0900 Subject: [PATCH 12/73] =?UTF-8?q?refactor=20:=20console=20=EC=95=A0?= =?UTF-8?q?=ED=94=8C=EB=A6=AC=EC=BC=80=EC=9D=B4=EC=85=98=20=ED=8E=98?= =?UTF-8?q?=ED=82=A4=EC=A7=80=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../VoucherManagementSystemApplication.java | 2 +- .../application/CommandCustomerApplication.java | 4 ++-- .../application/CommandMainApplication.java | 6 +++--- .../application/CommandWalletApplication.java | 4 ++-- .../application/RunnableCommandApplication.java | 2 +- .../controller/ConsoleBlacklistController.java | 6 +++--- .../controller/ConsoleCustomerController.java | 6 +++--- .../controller/ConsoleVoucherController.java | 6 +++--- .../controller/ConsoleWalletController.java | 6 +++--- 9 files changed, 21 insertions(+), 21 deletions(-) rename src/main/java/team/marco/voucher_management_system/{ => console_app}/application/CommandCustomerApplication.java (94%) rename src/main/java/team/marco/voucher_management_system/{ => console_app}/application/CommandMainApplication.java (92%) rename src/main/java/team/marco/voucher_management_system/{ => console_app}/application/CommandWalletApplication.java (94%) rename src/main/java/team/marco/voucher_management_system/{ => console_app}/application/RunnableCommandApplication.java (81%) rename src/main/java/team/marco/voucher_management_system/{ => console_app}/controller/ConsoleBlacklistController.java (87%) rename src/main/java/team/marco/voucher_management_system/{ => console_app}/controller/ConsoleCustomerController.java (95%) rename src/main/java/team/marco/voucher_management_system/{ => console_app}/controller/ConsoleVoucherController.java (93%) rename src/main/java/team/marco/voucher_management_system/{ => console_app}/controller/ConsoleWalletController.java (95%) diff --git a/src/main/java/team/marco/voucher_management_system/VoucherManagementSystemApplication.java b/src/main/java/team/marco/voucher_management_system/VoucherManagementSystemApplication.java index eaa9ff323b..08313424ea 100644 --- a/src/main/java/team/marco/voucher_management_system/VoucherManagementSystemApplication.java +++ b/src/main/java/team/marco/voucher_management_system/VoucherManagementSystemApplication.java @@ -7,7 +7,7 @@ import org.springframework.boot.context.properties.ConfigurationPropertiesScan; import org.springframework.context.ApplicationContext; import org.springframework.core.env.Environment; -import team.marco.voucher_management_system.application.CommandMainApplication; +import team.marco.voucher_management_system.console_app.application.CommandMainApplication; @SpringBootApplication @ConfigurationPropertiesScan diff --git a/src/main/java/team/marco/voucher_management_system/application/CommandCustomerApplication.java b/src/main/java/team/marco/voucher_management_system/console_app/application/CommandCustomerApplication.java similarity index 94% rename from src/main/java/team/marco/voucher_management_system/application/CommandCustomerApplication.java rename to src/main/java/team/marco/voucher_management_system/console_app/application/CommandCustomerApplication.java index 7a8f87813e..a8ba056e85 100644 --- a/src/main/java/team/marco/voucher_management_system/application/CommandCustomerApplication.java +++ b/src/main/java/team/marco/voucher_management_system/console_app/application/CommandCustomerApplication.java @@ -1,4 +1,4 @@ -package team.marco.voucher_management_system.application; +package team.marco.voucher_management_system.console_app.application; import java.util.NoSuchElementException; import org.slf4j.Logger; @@ -6,7 +6,7 @@ import org.springframework.dao.DuplicateKeyException; import org.springframework.jdbc.datasource.lookup.DataSourceLookupFailureException; import org.springframework.stereotype.Component; -import team.marco.voucher_management_system.controller.ConsoleCustomerController; +import team.marco.voucher_management_system.console_app.controller.ConsoleCustomerController; import team.marco.voucher_management_system.type_enum.CustomerCommandType; import team.marco.voucher_management_system.util.Console; diff --git a/src/main/java/team/marco/voucher_management_system/application/CommandMainApplication.java b/src/main/java/team/marco/voucher_management_system/console_app/application/CommandMainApplication.java similarity index 92% rename from src/main/java/team/marco/voucher_management_system/application/CommandMainApplication.java rename to src/main/java/team/marco/voucher_management_system/console_app/application/CommandMainApplication.java index 2dc11726b3..09e0736de7 100644 --- a/src/main/java/team/marco/voucher_management_system/application/CommandMainApplication.java +++ b/src/main/java/team/marco/voucher_management_system/console_app/application/CommandMainApplication.java @@ -1,11 +1,11 @@ -package team.marco.voucher_management_system.application; +package team.marco.voucher_management_system.console_app.application; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.jdbc.CannotGetJdbcConnectionException; import org.springframework.stereotype.Component; -import team.marco.voucher_management_system.controller.ConsoleBlacklistController; -import team.marco.voucher_management_system.controller.ConsoleVoucherController; +import team.marco.voucher_management_system.console_app.controller.ConsoleBlacklistController; +import team.marco.voucher_management_system.console_app.controller.ConsoleVoucherController; import team.marco.voucher_management_system.type_enum.MainCommandType; import team.marco.voucher_management_system.util.Console; diff --git a/src/main/java/team/marco/voucher_management_system/application/CommandWalletApplication.java b/src/main/java/team/marco/voucher_management_system/console_app/application/CommandWalletApplication.java similarity index 94% rename from src/main/java/team/marco/voucher_management_system/application/CommandWalletApplication.java rename to src/main/java/team/marco/voucher_management_system/console_app/application/CommandWalletApplication.java index ab92e8c2d1..985483743c 100644 --- a/src/main/java/team/marco/voucher_management_system/application/CommandWalletApplication.java +++ b/src/main/java/team/marco/voucher_management_system/console_app/application/CommandWalletApplication.java @@ -1,4 +1,4 @@ -package team.marco.voucher_management_system.application; +package team.marco.voucher_management_system.console_app.application; import java.util.NoSuchElementException; import org.slf4j.Logger; @@ -7,7 +7,7 @@ import org.springframework.dao.EmptyResultDataAccessException; import org.springframework.jdbc.UncategorizedSQLException; import org.springframework.stereotype.Component; -import team.marco.voucher_management_system.controller.ConsoleWalletController; +import team.marco.voucher_management_system.console_app.controller.ConsoleWalletController; import team.marco.voucher_management_system.type_enum.WalletCommandType; import team.marco.voucher_management_system.util.Console; diff --git a/src/main/java/team/marco/voucher_management_system/application/RunnableCommandApplication.java b/src/main/java/team/marco/voucher_management_system/console_app/application/RunnableCommandApplication.java similarity index 81% rename from src/main/java/team/marco/voucher_management_system/application/RunnableCommandApplication.java rename to src/main/java/team/marco/voucher_management_system/console_app/application/RunnableCommandApplication.java index 212fb591e3..498d161298 100644 --- a/src/main/java/team/marco/voucher_management_system/application/RunnableCommandApplication.java +++ b/src/main/java/team/marco/voucher_management_system/console_app/application/RunnableCommandApplication.java @@ -1,4 +1,4 @@ -package team.marco.voucher_management_system.application; +package team.marco.voucher_management_system.console_app.application; public abstract class RunnableCommandApplication { protected boolean runningFlag; diff --git a/src/main/java/team/marco/voucher_management_system/controller/ConsoleBlacklistController.java b/src/main/java/team/marco/voucher_management_system/console_app/controller/ConsoleBlacklistController.java similarity index 87% rename from src/main/java/team/marco/voucher_management_system/controller/ConsoleBlacklistController.java rename to src/main/java/team/marco/voucher_management_system/console_app/controller/ConsoleBlacklistController.java index 707aedbc41..bb55f9bd3a 100644 --- a/src/main/java/team/marco/voucher_management_system/controller/ConsoleBlacklistController.java +++ b/src/main/java/team/marco/voucher_management_system/console_app/controller/ConsoleBlacklistController.java @@ -1,12 +1,12 @@ -package team.marco.voucher_management_system.controller; +package team.marco.voucher_management_system.console_app.controller; import java.util.List; -import org.springframework.stereotype.Controller; +import org.springframework.stereotype.Component; import team.marco.voucher_management_system.model.BlacklistUser; import team.marco.voucher_management_system.service.BlacklistService; import team.marco.voucher_management_system.util.Console; -@Controller +@Component public class ConsoleBlacklistController { private static final String INFO_DELIMINATOR = "\n"; diff --git a/src/main/java/team/marco/voucher_management_system/controller/ConsoleCustomerController.java b/src/main/java/team/marco/voucher_management_system/console_app/controller/ConsoleCustomerController.java similarity index 95% rename from src/main/java/team/marco/voucher_management_system/controller/ConsoleCustomerController.java rename to src/main/java/team/marco/voucher_management_system/console_app/controller/ConsoleCustomerController.java index 037197251e..7eb5ede848 100644 --- a/src/main/java/team/marco/voucher_management_system/controller/ConsoleCustomerController.java +++ b/src/main/java/team/marco/voucher_management_system/console_app/controller/ConsoleCustomerController.java @@ -1,13 +1,13 @@ -package team.marco.voucher_management_system.controller; +package team.marco.voucher_management_system.console_app.controller; import java.text.MessageFormat; import java.util.List; -import org.springframework.stereotype.Controller; +import org.springframework.stereotype.Component; import team.marco.voucher_management_system.model.Customer; import team.marco.voucher_management_system.service.CustomerService; import team.marco.voucher_management_system.util.Console; -@Controller +@Component public class ConsoleCustomerController { private static final String INFO_DELIMINATOR = MessageFormat.format("\n{0}\n", "-".repeat(42)); diff --git a/src/main/java/team/marco/voucher_management_system/controller/ConsoleVoucherController.java b/src/main/java/team/marco/voucher_management_system/console_app/controller/ConsoleVoucherController.java similarity index 93% rename from src/main/java/team/marco/voucher_management_system/controller/ConsoleVoucherController.java rename to src/main/java/team/marco/voucher_management_system/console_app/controller/ConsoleVoucherController.java index 9dbc2c2641..a41205b6ca 100644 --- a/src/main/java/team/marco/voucher_management_system/controller/ConsoleVoucherController.java +++ b/src/main/java/team/marco/voucher_management_system/console_app/controller/ConsoleVoucherController.java @@ -1,13 +1,13 @@ -package team.marco.voucher_management_system.controller; +package team.marco.voucher_management_system.console_app.controller; import java.text.MessageFormat; import java.util.List; -import org.springframework.stereotype.Controller; +import org.springframework.stereotype.Component; import team.marco.voucher_management_system.model.Voucher; import team.marco.voucher_management_system.service.VoucherService; import team.marco.voucher_management_system.util.Console; -@Controller +@Component public class ConsoleVoucherController { private static final String INFO_DELIMINATOR = MessageFormat.format("\n{0}\n", "-".repeat(42)); diff --git a/src/main/java/team/marco/voucher_management_system/controller/ConsoleWalletController.java b/src/main/java/team/marco/voucher_management_system/console_app/controller/ConsoleWalletController.java similarity index 95% rename from src/main/java/team/marco/voucher_management_system/controller/ConsoleWalletController.java rename to src/main/java/team/marco/voucher_management_system/console_app/controller/ConsoleWalletController.java index 18a76b038d..7ca8a7af7e 100644 --- a/src/main/java/team/marco/voucher_management_system/controller/ConsoleWalletController.java +++ b/src/main/java/team/marco/voucher_management_system/console_app/controller/ConsoleWalletController.java @@ -1,14 +1,14 @@ -package team.marco.voucher_management_system.controller; +package team.marco.voucher_management_system.console_app.controller; import java.text.MessageFormat; import java.util.List; -import org.springframework.stereotype.Controller; +import org.springframework.stereotype.Component; import team.marco.voucher_management_system.model.Customer; import team.marco.voucher_management_system.model.Voucher; import team.marco.voucher_management_system.service.WalletService; import team.marco.voucher_management_system.util.Console; -@Controller +@Component public class ConsoleWalletController { private static final String INFO_DELIMINATOR = MessageFormat.format("\n{0}\n", "-".repeat(42)); From 383b178acfc24ead544ef39d9b2a55e195f9186f Mon Sep 17 00:00:00 2001 From: ASak1104 Date: Sun, 5 Nov 2023 14:05:35 +0900 Subject: [PATCH 13/73] =?UTF-8?q?fix=20:=20=EC=9E=98=EB=AA=BB=EB=90=9C=20u?= =?UTF-8?q?uid=EA=B0=80=20=EC=9E=85=EB=A0=A5=20=EB=90=90=EC=9D=84=20?= =?UTF-8?q?=EB=95=8C=EC=9D=98=20=EC=98=88=EC=99=B8=EC=B2=98=EB=A6=AC=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../repository/JdbcCustomerRepository.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/team/marco/voucher_management_system/repository/JdbcCustomerRepository.java b/src/main/java/team/marco/voucher_management_system/repository/JdbcCustomerRepository.java index 3c426f392b..5e1f395c5a 100644 --- a/src/main/java/team/marco/voucher_management_system/repository/JdbcCustomerRepository.java +++ b/src/main/java/team/marco/voucher_management_system/repository/JdbcCustomerRepository.java @@ -13,6 +13,7 @@ import java.util.Optional; import java.util.UUID; import org.springframework.dao.EmptyResultDataAccessException; +import org.springframework.jdbc.UncategorizedSQLException; import org.springframework.jdbc.core.RowMapper; import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; import org.springframework.stereotype.Repository; @@ -76,7 +77,7 @@ public Optional findById(String id) { customerRowMapper); return Optional.ofNullable(customer); - } catch (EmptyResultDataAccessException e) { + } catch (EmptyResultDataAccessException | UncategorizedSQLException e) { return Optional.empty(); } } From 2065a1e0c847fc84916a3d93fb3b372c01293f86 Mon Sep 17 00:00:00 2001 From: ASak1104 Date: Sun, 5 Nov 2023 14:14:03 +0900 Subject: [PATCH 14/73] =?UTF-8?q?logging=20:=20=EB=A1=9C=EA=B9=85=20?= =?UTF-8?q?=ED=8F=AC=EC=9D=B8=ED=8A=B8=20=EC=BB=B7=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../marco/voucher_management_system/aspect/LoggingPointCut.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/team/marco/voucher_management_system/aspect/LoggingPointCut.java b/src/main/java/team/marco/voucher_management_system/aspect/LoggingPointCut.java index e31b0c675f..c4141fb709 100644 --- a/src/main/java/team/marco/voucher_management_system/aspect/LoggingPointCut.java +++ b/src/main/java/team/marco/voucher_management_system/aspect/LoggingPointCut.java @@ -6,7 +6,7 @@ public final class LoggingPointCut { private LoggingPointCut() { } - @Pointcut("execution(* team.marco.voucher_management_system.controller..*(..))") + @Pointcut("execution(* team.marco.voucher_management_system..controller..*(..))") public static void controllerMethodPointcut() { } From 641def9dde986f8f1a9202ff25eb1ffa8e41fb9e Mon Sep 17 00:00:00 2001 From: ASak1104 Date: Sun, 5 Nov 2023 14:45:51 +0900 Subject: [PATCH 15/73] =?UTF-8?q?chore=20:=20spring=20web=20=EC=9D=98?= =?UTF-8?q?=EC=A1=B4=EC=84=B1=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 6eec52269b..b8dd9725c6 100644 --- a/build.gradle +++ b/build.gradle @@ -18,9 +18,10 @@ repositories { dependencies { implementation 'org.springframework.boot:spring-boot-starter' - implementation 'com.fasterxml.jackson.core:jackson-databind:2.15.2' implementation 'org.springframework.boot:spring-boot-starter-aop' + implementation 'org.springframework.boot:spring-boot-starter-web' implementation 'org.springframework.boot:spring-boot-starter-jdbc' + implementation 'com.fasterxml.jackson.core:jackson-databind:2.15.2' implementation 'com.mysql:mysql-connector-j:8.1.0' testImplementation 'org.springframework.boot:spring-boot-starter-test' } From ae21ab6ce739ebaf2b2e93ad1c3b1f9af05ee845 Mon Sep 17 00:00:00 2001 From: ASak1104 Date: Sun, 5 Nov 2023 14:46:30 +0900 Subject: [PATCH 16/73] =?UTF-8?q?style=20:=20=EB=A9=94=EC=84=9C=EB=93=9C?= =?UTF-8?q?=20=EC=9D=B4=EB=A6=84=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../console_app/controller/ConsoleVoucherController.java | 2 +- .../marco/voucher_management_system/service/VoucherService.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/team/marco/voucher_management_system/console_app/controller/ConsoleVoucherController.java b/src/main/java/team/marco/voucher_management_system/console_app/controller/ConsoleVoucherController.java index a41205b6ca..e049a96481 100644 --- a/src/main/java/team/marco/voucher_management_system/console_app/controller/ConsoleVoucherController.java +++ b/src/main/java/team/marco/voucher_management_system/console_app/controller/ConsoleVoucherController.java @@ -32,7 +32,7 @@ public void selectVoucher() { } public void voucherList() { - List vouchers = voucherService.getVouchersInfo() + List vouchers = voucherService.getVouchers() .stream() .map(Voucher::getInfo) .toList(); diff --git a/src/main/java/team/marco/voucher_management_system/service/VoucherService.java b/src/main/java/team/marco/voucher_management_system/service/VoucherService.java index 1116b928d2..1ee62c805c 100644 --- a/src/main/java/team/marco/voucher_management_system/service/VoucherService.java +++ b/src/main/java/team/marco/voucher_management_system/service/VoucherService.java @@ -25,7 +25,7 @@ public void createPercentDiscountVoucher(int percent) { voucherRepository.save(voucher); } - public List getVouchersInfo() { + public List getVouchers() { return voucherRepository.findAll(); } } From 4921225bdb7c6e1cb1eb2285bf924b89bed167dd Mon Sep 17 00:00:00 2001 From: ASak1104 Date: Sun, 5 Nov 2023 16:02:05 +0900 Subject: [PATCH 17/73] =?UTF-8?q?feat=20:=20voucher=20=EC=83=9D=EC=84=B1?= =?UTF-8?q?=20=ED=95=84=EB=93=9C=20=EC=9D=BC=EC=9E=90=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../model/FixedAmountVoucher.java | 9 ++++++ .../model/LoadedVoucher.java | 5 +++- .../model/PercentDiscountVoucher.java | 9 ++++++ .../model/Voucher.java | 18 ++++++++++++ .../repository/JdbcVoucherRepository.java | 4 ++- .../type_enum/VoucherType.java | 10 +++++-- src/main/resources/sample_data.json | 28 +++++++++++++++---- src/main/resources/schema.sql | 7 +++-- .../JSONFileVoucherRepositoryTest.java | 8 +++++- 9 files changed, 85 insertions(+), 13 deletions(-) diff --git a/src/main/java/team/marco/voucher_management_system/model/FixedAmountVoucher.java b/src/main/java/team/marco/voucher_management_system/model/FixedAmountVoucher.java index f9c254acd3..5242b062c8 100644 --- a/src/main/java/team/marco/voucher_management_system/model/FixedAmountVoucher.java +++ b/src/main/java/team/marco/voucher_management_system/model/FixedAmountVoucher.java @@ -3,6 +3,7 @@ import static java.text.MessageFormat.format; import java.text.MessageFormat; +import java.time.LocalDateTime; import java.util.UUID; import team.marco.voucher_management_system.type_enum.VoucherType; @@ -20,7 +21,15 @@ public FixedAmountVoucher(int amount) { public FixedAmountVoucher(UUID id, int amount) { super(id); + + this.amount = amount; + } + + public FixedAmountVoucher(UUID id, int amount, LocalDateTime createAt) { + super(id); + this.amount = amount; + this.createAt = createAt; } private static void validate(int amount) { diff --git a/src/main/java/team/marco/voucher_management_system/model/LoadedVoucher.java b/src/main/java/team/marco/voucher_management_system/model/LoadedVoucher.java index d9cabad6f1..fc02120e11 100644 --- a/src/main/java/team/marco/voucher_management_system/model/LoadedVoucher.java +++ b/src/main/java/team/marco/voucher_management_system/model/LoadedVoucher.java @@ -1,5 +1,6 @@ package team.marco.voucher_management_system.model; +import java.time.LocalDateTime; import java.util.UUID; import team.marco.voucher_management_system.type_enum.VoucherType; @@ -11,10 +12,12 @@ private LoadedVoucher() { // for object mapper deserializing } - public LoadedVoucher(UUID id, VoucherType type, int data) { + public LoadedVoucher(UUID id, VoucherType type, int data, LocalDateTime createAt) { super(id); + this.type = type; this.data = data; + this.createAt = createAt; } @Override diff --git a/src/main/java/team/marco/voucher_management_system/model/PercentDiscountVoucher.java b/src/main/java/team/marco/voucher_management_system/model/PercentDiscountVoucher.java index 3e19a67c02..5f77fa4488 100644 --- a/src/main/java/team/marco/voucher_management_system/model/PercentDiscountVoucher.java +++ b/src/main/java/team/marco/voucher_management_system/model/PercentDiscountVoucher.java @@ -3,6 +3,7 @@ import static java.text.MessageFormat.format; import java.text.MessageFormat; +import java.time.LocalDateTime; import java.util.UUID; import team.marco.voucher_management_system.type_enum.VoucherType; @@ -20,7 +21,15 @@ public PercentDiscountVoucher(int percent) { public PercentDiscountVoucher(UUID id, int percent) { super(id); + + this.percent = percent; + } + + public PercentDiscountVoucher(UUID id, int percent, LocalDateTime createAt) { + super(id); + this.percent = percent; + this.createAt = createAt; } private void validate(int percent) { diff --git a/src/main/java/team/marco/voucher_management_system/model/Voucher.java b/src/main/java/team/marco/voucher_management_system/model/Voucher.java index 6f8b9a3716..788901921d 100644 --- a/src/main/java/team/marco/voucher_management_system/model/Voucher.java +++ b/src/main/java/team/marco/voucher_management_system/model/Voucher.java @@ -1,24 +1,42 @@ package team.marco.voucher_management_system.model; import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer; +import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer; +import java.time.LocalDateTime; import java.util.UUID; import team.marco.voucher_management_system.type_enum.VoucherType; public abstract class Voucher { protected final UUID id; + @JsonSerialize(using = LocalDateTimeSerializer.class) + @JsonDeserialize(using = LocalDateTimeDeserializer.class) + protected LocalDateTime createAt; protected Voucher() { this.id = UUID.randomUUID(); + this.createAt = LocalDateTime.now(); } protected Voucher(UUID id) { this.id = id; + this.createAt = LocalDateTime.now(); + } + + public boolean isSameId(UUID id) { + return this.id.equals(id); } public final UUID getId() { return id; } + public LocalDateTime getCreateAt() { + return createAt; + } + public abstract VoucherType getType(); public abstract int getData(); diff --git a/src/main/java/team/marco/voucher_management_system/repository/JdbcVoucherRepository.java b/src/main/java/team/marco/voucher_management_system/repository/JdbcVoucherRepository.java index 0b8d663070..bef3f44de7 100644 --- a/src/main/java/team/marco/voucher_management_system/repository/JdbcVoucherRepository.java +++ b/src/main/java/team/marco/voucher_management_system/repository/JdbcVoucherRepository.java @@ -2,6 +2,7 @@ import java.sql.ResultSet; import java.sql.SQLException; +import java.time.LocalDateTime; import java.util.List; import java.util.Map; import java.util.UUID; @@ -34,8 +35,9 @@ private static Voucher mapToVoucher(ResultSet resultSet, int ignored) throws SQL UUID id = UUIDConverter.convert(idBytes); VoucherType type = VoucherType.valueOf(typeString); int data = Integer.parseInt(dataString); + LocalDateTime createAt = resultSet.getTimestamp("created_at").toLocalDateTime(); - LoadedVoucher loadedVoucher = new LoadedVoucher(id, type, data); + LoadedVoucher loadedVoucher = new LoadedVoucher(id, type, data, createAt); return VoucherType.convertVoucher(loadedVoucher); } diff --git a/src/main/java/team/marco/voucher_management_system/type_enum/VoucherType.java b/src/main/java/team/marco/voucher_management_system/type_enum/VoucherType.java index a81ecdc303..6a6ace36fa 100644 --- a/src/main/java/team/marco/voucher_management_system/type_enum/VoucherType.java +++ b/src/main/java/team/marco/voucher_management_system/type_enum/VoucherType.java @@ -10,8 +10,14 @@ public enum VoucherType { public static Voucher convertVoucher(LoadedVoucher loadedVoucher) { return switch (loadedVoucher.getType()) { - case FIXED -> new FixedAmountVoucher(loadedVoucher.getId(), loadedVoucher.getData()); - case PERCENT -> new PercentDiscountVoucher(loadedVoucher.getId(), loadedVoucher.getData()); + case FIXED -> new FixedAmountVoucher( + loadedVoucher.getId(), + loadedVoucher.getData(), + loadedVoucher.getCreateAt()); + case PERCENT -> new PercentDiscountVoucher( + loadedVoucher.getId(), + loadedVoucher.getData(), + loadedVoucher.getCreateAt()); }; } } diff --git a/src/main/resources/sample_data.json b/src/main/resources/sample_data.json index ced95cadef..77292e0a43 100644 --- a/src/main/resources/sample_data.json +++ b/src/main/resources/sample_data.json @@ -1,12 +1,30 @@ [ { - "id": "2f1bdafa-c02f-430f-823a-da6704deac70", - "type": "PERCENT", - "data": 100 + "id": "dd777f5b-7113-428c-af9a-e37465006c0e", + "createAt": [ + 2023, + 11, + 5, + 15, + 40, + 31, + 8486000 + ], + "type": "FIXED", + "data": 1000 }, { - "id": "a5124642-c6f4-4f22-9e2b-9d25f98499d4", + "id": "7273b0f3-6db5-444d-944c-8c5b8523fd4b", + "createAt": [ + 2023, + 11, + 5, + 15, + 58, + 56, + 259204000 + ], "type": "FIXED", - "data": 10000 + "data": 20 } ] diff --git a/src/main/resources/schema.sql b/src/main/resources/schema.sql index 63e5f37948..d5cd3c8f14 100644 --- a/src/main/resources/schema.sql +++ b/src/main/resources/schema.sql @@ -1,8 +1,9 @@ CREATE TABLE voucher ( - id BINARY(16) PRIMARY KEY, - type VARCHAR(16) NOT NULL, - data INT NOT NULL + id BINARY(16) PRIMARY KEY, + type VARCHAR(16) NOT NULL, + data INT NOT NULL, + created_at datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP (6) ); CREATE TABLE customer diff --git a/src/test/java/team/marco/voucher_management_system/repository/JSONFileVoucherRepositoryTest.java b/src/test/java/team/marco/voucher_management_system/repository/JSONFileVoucherRepositoryTest.java index ef4e23d597..55d0c16ff0 100644 --- a/src/test/java/team/marco/voucher_management_system/repository/JSONFileVoucherRepositoryTest.java +++ b/src/test/java/team/marco/voucher_management_system/repository/JSONFileVoucherRepositoryTest.java @@ -27,7 +27,13 @@ class JSONFileVoucherRepositoryTest extends VoucherRepositoryTest { private static final String SETUP_DATA; static { - SETUP_DATA = "[{\"id\": \"a5124642-c6f4-4f22-9e2b-9d25f98499d4\",\"type\": \"FIXED\",\"data\": 10000}]"; + SETUP_DATA = """ + [{ + "id": "a5124642-c6f4-4f22-9e2b-9d25f98499d4", + "type": "FIXED", + "data": 10000, + "createAt": [2023,10,8,6,0,43,644828000] + }]"""; } @Autowired From 3ac74b5af07ca9392700307464aae95d2663ba78 Mon Sep 17 00:00:00 2001 From: ASak1104 Date: Sun, 5 Nov 2023 16:49:51 +0900 Subject: [PATCH 18/73] =?UTF-8?q?feat=20:=20voucherRepository=20=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../model/Voucher.java | 4 +++ .../repository/JSONFileVoucherRepository.java | 18 ++++++++++++ .../repository/JdbcVoucherRepository.java | 28 +++++++++++++++++++ .../repository/MemoryVoucherRepository.java | 19 +++++++++++++ .../repository/VoucherRepository.java | 7 +++++ 5 files changed, 76 insertions(+) diff --git a/src/main/java/team/marco/voucher_management_system/model/Voucher.java b/src/main/java/team/marco/voucher_management_system/model/Voucher.java index 788901921d..e0e7f68e16 100644 --- a/src/main/java/team/marco/voucher_management_system/model/Voucher.java +++ b/src/main/java/team/marco/voucher_management_system/model/Voucher.java @@ -29,6 +29,10 @@ public boolean isSameId(UUID id) { return this.id.equals(id); } + public boolean isSameType(VoucherType voucherType) { + return getType() == voucherType; + } + public final UUID getId() { return id; } diff --git a/src/main/java/team/marco/voucher_management_system/repository/JSONFileVoucherRepository.java b/src/main/java/team/marco/voucher_management_system/repository/JSONFileVoucherRepository.java index e72ed8142a..6479844e81 100644 --- a/src/main/java/team/marco/voucher_management_system/repository/JSONFileVoucherRepository.java +++ b/src/main/java/team/marco/voucher_management_system/repository/JSONFileVoucherRepository.java @@ -8,6 +8,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.UUID; import org.springframework.beans.factory.DisposableBean; import org.springframework.context.annotation.Profile; @@ -64,6 +65,23 @@ public List findAll() { .toList(); } + @Override + public Optional findById(UUID id) { + if (!voucherMap.containsKey(id)) { + return Optional.empty(); + } + + return Optional.of(voucherMap.get(id)); + } + + @Override + public List findByType(VoucherType voucherType) { + return voucherMap.values() + .stream() + .filter(voucher -> voucher.isSameType(voucherType)) + .toList(); + } + @Override public void destroy() { try { diff --git a/src/main/java/team/marco/voucher_management_system/repository/JdbcVoucherRepository.java b/src/main/java/team/marco/voucher_management_system/repository/JdbcVoucherRepository.java index bef3f44de7..b833b6c70b 100644 --- a/src/main/java/team/marco/voucher_management_system/repository/JdbcVoucherRepository.java +++ b/src/main/java/team/marco/voucher_management_system/repository/JdbcVoucherRepository.java @@ -3,11 +3,15 @@ import java.sql.ResultSet; import java.sql.SQLException; import java.time.LocalDateTime; +import java.util.Collections; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.UUID; import org.springframework.context.annotation.Profile; import org.springframework.dao.DataAccessResourceFailureException; +import org.springframework.dao.EmptyResultDataAccessException; +import org.springframework.jdbc.UncategorizedSQLException; import org.springframework.jdbc.core.RowMapper; import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; import org.springframework.stereotype.Repository; @@ -58,6 +62,30 @@ public List findAll() { return jdbcTemplate.query("SELECT * FROM voucher", voucherRowMapper); } + @Override + public Optional findById(UUID id) { + try { + Voucher voucher = jdbcTemplate.queryForObject( + "SELECT * FROM voucher" + + " WHERE id = UUID_TO_BIN(:id)", + Collections.singletonMap("id", id.toString().getBytes()), + voucherRowMapper); + + return Optional.ofNullable(voucher); + } catch (EmptyResultDataAccessException | UncategorizedSQLException e) { + return Optional.empty(); + } + } + + @Override + public List findByType(VoucherType voucherType) { + return jdbcTemplate.query( + "SELECT * FROM voucher" + + " WHERE type = :type", + Collections.singletonMap("type", voucherType.toString()), + voucherRowMapper); + } + private Map voucherToMap(Voucher voucher) { return Map.ofEntries( Map.entry("id", voucher.getId().toString().getBytes()), diff --git a/src/main/java/team/marco/voucher_management_system/repository/MemoryVoucherRepository.java b/src/main/java/team/marco/voucher_management_system/repository/MemoryVoucherRepository.java index 5e8021ab39..1616d005b9 100644 --- a/src/main/java/team/marco/voucher_management_system/repository/MemoryVoucherRepository.java +++ b/src/main/java/team/marco/voucher_management_system/repository/MemoryVoucherRepository.java @@ -3,10 +3,12 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.UUID; import org.springframework.context.annotation.Profile; import org.springframework.stereotype.Repository; import team.marco.voucher_management_system.model.Voucher; +import team.marco.voucher_management_system.type_enum.VoucherType; @Profile({"debug", "test"}) @Repository @@ -24,4 +26,21 @@ public List findAll() { .stream() .toList(); } + + @Override + public Optional findById(UUID id) { + if (!voucherMap.containsKey(id)) { + return Optional.empty(); + } + + return Optional.of(voucherMap.get(id)); + } + + @Override + public List findByType(VoucherType voucherType) { + return voucherMap.values() + .stream() + .filter(voucher -> voucher.isSameType(voucherType)) + .toList(); + } } diff --git a/src/main/java/team/marco/voucher_management_system/repository/VoucherRepository.java b/src/main/java/team/marco/voucher_management_system/repository/VoucherRepository.java index afd4feeb0c..fe071867f7 100644 --- a/src/main/java/team/marco/voucher_management_system/repository/VoucherRepository.java +++ b/src/main/java/team/marco/voucher_management_system/repository/VoucherRepository.java @@ -1,10 +1,17 @@ package team.marco.voucher_management_system.repository; import java.util.List; +import java.util.Optional; +import java.util.UUID; import team.marco.voucher_management_system.model.Voucher; +import team.marco.voucher_management_system.type_enum.VoucherType; public interface VoucherRepository { void save(Voucher voucher); List findAll(); + + Optional findById(UUID id); + + List findByType(VoucherType voucherType); } From 8ee85f0b0b994a8636a84126f51181f14cf51918 Mon Sep 17 00:00:00 2001 From: ASak1104 Date: Sun, 5 Nov 2023 16:50:16 +0900 Subject: [PATCH 19/73] =?UTF-8?q?test=20:=20voucher=20=EB=AA=A8=EB=8D=B8?= =?UTF-8?q?=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../model/FixedAmountVoucherTest.java | 5 ++ .../model/PercentDiscountVoucherTest.java | 5 ++ .../model/VoucherTest.java | 73 +++++++++++++++++++ 3 files changed, 83 insertions(+) diff --git a/src/test/java/team/marco/voucher_management_system/model/FixedAmountVoucherTest.java b/src/test/java/team/marco/voucher_management_system/model/FixedAmountVoucherTest.java index 7be949f533..f34cc50d30 100644 --- a/src/test/java/team/marco/voucher_management_system/model/FixedAmountVoucherTest.java +++ b/src/test/java/team/marco/voucher_management_system/model/FixedAmountVoucherTest.java @@ -17,6 +17,11 @@ class FixedAmountVoucherTest extends VoucherTest { private static final int MAXIMUM_AMOUNT = (int) 1e9; private static final int MINIMUM_AMOUNT = 1; + @Override + protected VoucherType getTargetType() { + return FIXED_VOUCHER_TYPE; + } + @Override protected int generateValidData() { return (MAXIMUM_AMOUNT + MINIMUM_AMOUNT) / 2; diff --git a/src/test/java/team/marco/voucher_management_system/model/PercentDiscountVoucherTest.java b/src/test/java/team/marco/voucher_management_system/model/PercentDiscountVoucherTest.java index f0b94ac462..fcbe3661d1 100644 --- a/src/test/java/team/marco/voucher_management_system/model/PercentDiscountVoucherTest.java +++ b/src/test/java/team/marco/voucher_management_system/model/PercentDiscountVoucherTest.java @@ -17,6 +17,11 @@ class PercentDiscountVoucherTest extends VoucherTest { private static final int MAXIMUM_PERCENT = 100; private static final int MINIMUM_PERCENT = 1; + @Override + protected VoucherType getTargetType() { + return PERCENT_VOUCHER_TYPE; + } + @Override protected int generateValidData() { return (MAXIMUM_PERCENT + MINIMUM_PERCENT) / 2; diff --git a/src/test/java/team/marco/voucher_management_system/model/VoucherTest.java b/src/test/java/team/marco/voucher_management_system/model/VoucherTest.java index 689998179a..4fe3c547e1 100644 --- a/src/test/java/team/marco/voucher_management_system/model/VoucherTest.java +++ b/src/test/java/team/marco/voucher_management_system/model/VoucherTest.java @@ -7,12 +7,16 @@ import static org.hamcrest.Matchers.notNullValue; import java.text.NumberFormat; +import java.util.Arrays; import java.util.UUID; import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import team.marco.voucher_management_system.type_enum.VoucherType; abstract class VoucherTest { + abstract protected VoucherType getTargetType(); + abstract protected int generateValidData(); abstract protected Voucher generateVoucher(int data); @@ -61,4 +65,73 @@ void testGetInfo() { assertThat(voucherInfo, containsString(id.toString())); assertThat(voucherInfo, containsString(NumberFormat.getIntegerInstance().format(initData))); } + + @Nested + @DisplayName("id 판별 테스트") + class TestIsSameId { + @Test + @DisplayName("동일한 id일 경우 true를 반환한다.") + void isSameId() { + // given + Voucher voucher = generateVoucher(generateValidData()); + UUID voucherId = voucher.getId(); + + // when + boolean isSameId = voucher.isSameId(voucherId); + + // then + assertThat(isSameId, is(true)); + } + + @Test + @DisplayName("동일하지 않은 id일 경우 false를 반환한다.") + void isNotSameId() { + // given + Voucher voucher = generateVoucher(generateValidData()); + Voucher otherVoucher = generateVoucher(generateValidData()); + UUID voucherId = otherVoucher.getId(); + + // when + boolean isSameId = voucher.isSameId(voucherId); + + // then + assertThat(isSameId, is(false)); + } + } + + @Nested + @DisplayName("type 판별 테스트") + class TestIsSameType { + @Test + @DisplayName("동일한 type일 경우 true를 반환한다.") + void isSameType() { + // given + Voucher voucher = generateVoucher(generateValidData()); + VoucherType targetType = getTargetType(); + + // when + boolean isSameType = voucher.isSameType(targetType); + + // then + assertThat(isSameType, is(true)); + } + + @Test + @DisplayName("동일하지 않은 type일 경우 false를 반환한다.") + void isNotSameType() { + // given + Voucher voucher = generateVoucher(generateValidData()); + VoucherType targetType = getTargetType(); + VoucherType otherType = Arrays.stream(VoucherType.values()) + .filter(voucherType -> voucherType != targetType) + .findFirst() + .orElseThrow(); + + // when + boolean isSameType = voucher.isSameType(otherType); + + // then + assertThat(isSameType, is(false)); + } + } } From 737411bd47838d17a6eb8ddb1db03a21585cafa1 Mon Sep 17 00:00:00 2001 From: ASak1104 Date: Sun, 5 Nov 2023 16:50:36 +0900 Subject: [PATCH 20/73] =?UTF-8?q?test=20:=20id,=20type=20=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../JdbcCustomerRepositoryTest.java | 1 - .../repository/VoucherRepositoryTest.java | 75 +++++++++++++++++++ 2 files changed, 75 insertions(+), 1 deletion(-) diff --git a/src/test/java/team/marco/voucher_management_system/repository/JdbcCustomerRepositoryTest.java b/src/test/java/team/marco/voucher_management_system/repository/JdbcCustomerRepositoryTest.java index a3bac98d27..303d7f1c1f 100644 --- a/src/test/java/team/marco/voucher_management_system/repository/JdbcCustomerRepositoryTest.java +++ b/src/test/java/team/marco/voucher_management_system/repository/JdbcCustomerRepositoryTest.java @@ -127,7 +127,6 @@ void success() { // given int seed = 100; Customer existCustomer = generateCustomer(seed + 1); - Customer notExistCustomer = generateCustomer(seed + 2); addTestCustomers(seed); repository.create(existCustomer); diff --git a/src/test/java/team/marco/voucher_management_system/repository/VoucherRepositoryTest.java b/src/test/java/team/marco/voucher_management_system/repository/VoucherRepositoryTest.java index 0f25d46efd..6f5c64cf6b 100644 --- a/src/test/java/team/marco/voucher_management_system/repository/VoucherRepositoryTest.java +++ b/src/test/java/team/marco/voucher_management_system/repository/VoucherRepositoryTest.java @@ -3,18 +3,23 @@ import static org.assertj.core.api.Assertions.assertThatNoException; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.empty; +import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.not; import static org.hamcrest.Matchers.notNullValue; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; +import java.util.Optional; import java.util.UUID; import org.assertj.core.api.Assertions; import org.assertj.core.api.ThrowableAssert.ThrowingCallable; import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import team.marco.voucher_management_system.model.FixedAmountVoucher; import team.marco.voucher_management_system.model.Voucher; +import team.marco.voucher_management_system.type_enum.VoucherType; abstract class VoucherRepositoryTest { protected abstract VoucherRepository getRepository(); @@ -76,4 +81,74 @@ void testFindAll() { Assertions.assertThat(retrievedIds).containsExactlyInAnyOrderElementsOf(generatedIds); } + + @Nested + @DisplayName("Voucher id 조회 테스트") + class TestFindById { + @Test + @DisplayName("id가 일치하는 Voucher가 존재할 경우 조회할 수 있어야 한다.") + void success() { + // given + VoucherRepository repository = getRepository(); + Voucher generatedVoucher = generateVoucher(); + UUID id = generatedVoucher.getId(); + + repository.save(generatedVoucher); + + // when + Optional optionalVoucher = repository.findById(id); + + // then + assertThat(optionalVoucher.isEmpty(), is(false)); + + Voucher voucher = optionalVoucher.get(); + + assertThat(voucher.getId(), is(id)); + } + + @Test + @DisplayName("id가 일치하는 고객이 없을 경우 빈 optional 객체를 반환한다.") + void emptyVoucher() { + // given + VoucherRepository repository = getRepository(); + Voucher notExistVoucher = generateVoucher(); + UUID notExistVoucherId = notExistVoucher.getId(); + + // when + Optional optionalVoucher = repository.findById(notExistVoucherId); + + // then + assertThat(optionalVoucher.isEmpty(), is(true)); + } + } + + @Test + @DisplayName("type이 일치하는 Voucher를 모두 반환한다.") + void testFindByType() { + // given + VoucherRepository repository = getRepository(); + List vouchers = List.of( + generateVoucher(), + generateVoucher(), + generateVoucher()); + List voucherTypes = Arrays.stream(VoucherType.values()).toList(); + + vouchers.forEach(repository::save); + + // when + List counts = voucherTypes.stream() + .map(repository::findByType) + .map(List::size) + .toList(); + + // then + List expectedCounts = voucherTypes.stream() + .map(voucherType -> vouchers.stream() + .filter(voucher -> voucher.isSameType(voucherType)) + .count()) + .map(Math::toIntExact) + .toList(); + + Assertions.assertThat(counts).containsExactlyElementsOf(expectedCounts); + } } From fb0987bcdaeeaaa9a57e6ddad810bef30b89daba Mon Sep 17 00:00:00 2001 From: ASak1104 Date: Sun, 5 Nov 2023 17:14:26 +0900 Subject: [PATCH 21/73] =?UTF-8?q?refactor=20:=20string=20uuid=20=EC=9D=B8?= =?UTF-8?q?=EC=9E=90=EB=A5=BC=20UUID=20=ED=83=80=EC=9E=85=EC=9C=BC?= =?UTF-8?q?=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/ConsoleCustomerController.java | 8 +++- .../controller/ConsoleWalletController.java | 15 +++--- .../facade/VoucherCustomerFacade.java | 4 +- .../facade/VoucherCustomerFacadeImpl.java | 8 ++-- .../repository/CustomerRepository.java | 3 +- .../repository/JdbcCustomerRepository.java | 7 ++- .../repository/JdbcWalletRepository.java | 47 ++++++++++--------- .../repository/WalletRepository.java | 8 ++-- .../service/CustomerService.java | 5 +- .../service/VoucherService.java | 9 ++++ .../service/WalletService.java | 12 ++--- .../util/UUIDConverter.java | 11 ++++- .../JdbcCustomerRepositoryTest.java | 6 +-- .../repository/JdbcWalletRepositoryTest.java | 21 ++++----- 14 files changed, 95 insertions(+), 69 deletions(-) diff --git a/src/main/java/team/marco/voucher_management_system/console_app/controller/ConsoleCustomerController.java b/src/main/java/team/marco/voucher_management_system/console_app/controller/ConsoleCustomerController.java index 7eb5ede848..373b9ccc1a 100644 --- a/src/main/java/team/marco/voucher_management_system/console_app/controller/ConsoleCustomerController.java +++ b/src/main/java/team/marco/voucher_management_system/console_app/controller/ConsoleCustomerController.java @@ -2,10 +2,12 @@ import java.text.MessageFormat; import java.util.List; +import java.util.UUID; import org.springframework.stereotype.Component; import team.marco.voucher_management_system.model.Customer; import team.marco.voucher_management_system.service.CustomerService; import team.marco.voucher_management_system.util.Console; +import team.marco.voucher_management_system.util.UUIDConverter; @Component public class ConsoleCustomerController { @@ -37,7 +39,8 @@ public void customerList() { public void updateCustomer() { Console.print("수정할 고객의 ID를 입력해 주세요."); - String id = Console.readString(); + String input = Console.readString(); + UUID id = UUIDConverter.convert(input); customerService.findById(id); @@ -51,7 +54,8 @@ public void updateCustomer() { public void findCustomerById() { Console.print("조회할 고객의 ID를 입력해 주세요."); - String id = Console.readString(); + String input = Console.readString(); + UUID id = UUIDConverter.convert(input); Customer customer = customerService.findById(id); diff --git a/src/main/java/team/marco/voucher_management_system/console_app/controller/ConsoleWalletController.java b/src/main/java/team/marco/voucher_management_system/console_app/controller/ConsoleWalletController.java index 7ca8a7af7e..d62d6adbfa 100644 --- a/src/main/java/team/marco/voucher_management_system/console_app/controller/ConsoleWalletController.java +++ b/src/main/java/team/marco/voucher_management_system/console_app/controller/ConsoleWalletController.java @@ -2,11 +2,13 @@ import java.text.MessageFormat; import java.util.List; +import java.util.UUID; import org.springframework.stereotype.Component; import team.marco.voucher_management_system.model.Customer; import team.marco.voucher_management_system.model.Voucher; import team.marco.voucher_management_system.service.WalletService; import team.marco.voucher_management_system.util.Console; +import team.marco.voucher_management_system.util.UUIDConverter; @Component public class ConsoleWalletController { @@ -21,12 +23,13 @@ public ConsoleWalletController(WalletService walletService) { public void supplyVoucher() { Console.print("쿠폰을 받을 고객 ID를 입력해주세요."); - String customerId = Console.readString(); + UUID customerId = UUIDConverter.convert(Console.readString()); + walletService.checkCustomerId(customerId); Console.print("지급할 쿠폰 ID를 입력해주세요."); - String voucherId = Console.readString(); + UUID voucherId = UUIDConverter.convert(Console.readString()); walletService.checkVoucherId(voucherId); if (walletService.supplyVoucher(customerId, voucherId) != 1) { @@ -41,7 +44,7 @@ public void supplyVoucher() { public void voucherList() { Console.print("보유 중인 쿠폰 목록을 확인할 고객 ID를 입력해주세요."); - String customerId = Console.readString(); + UUID customerId = UUIDConverter.convert(Console.readString()); List voucherInfos = walletService.findVouchersByCustomerId(customerId) .stream() @@ -55,12 +58,12 @@ public void voucherList() { public void returnVoucher() { Console.print("쿠폰을 반납할 고객 ID를 입력해주세요."); - String customerId = Console.readString(); + UUID customerId = UUIDConverter.convert(Console.readString()); walletService.checkCustomerId(customerId); Console.print("반납할 쿠폰 ID를 입력해주세요."); - String voucherId = Console.readString(); + UUID voucherId = UUIDConverter.convert(Console.readString()); walletService.checkVoucherId(voucherId); if (walletService.returnVoucher(customerId, voucherId) != 1) { @@ -75,7 +78,7 @@ public void returnVoucher() { public void customerList() { Console.print("보유 중인 고객 목록을 확인할 쿠폰 ID를 입력해주세요."); - String voucherId = Console.readString(); + UUID voucherId = UUIDConverter.convert(Console.readString()); walletService.checkVoucherId(voucherId); List customerInfos = walletService.findCustomersByVoucherId(voucherId) diff --git a/src/main/java/team/marco/voucher_management_system/facade/VoucherCustomerFacade.java b/src/main/java/team/marco/voucher_management_system/facade/VoucherCustomerFacade.java index 5255d8de39..194b87c402 100644 --- a/src/main/java/team/marco/voucher_management_system/facade/VoucherCustomerFacade.java +++ b/src/main/java/team/marco/voucher_management_system/facade/VoucherCustomerFacade.java @@ -6,9 +6,9 @@ import team.marco.voucher_management_system.model.Voucher; public interface VoucherCustomerFacade { - boolean hasVoucher(String voucherId); + boolean hasVoucher(UUID voucherId); - boolean hasCustomer(String customerId); + boolean hasCustomer(UUID customerId); List getVouchers(List voucherIds); diff --git a/src/main/java/team/marco/voucher_management_system/facade/VoucherCustomerFacadeImpl.java b/src/main/java/team/marco/voucher_management_system/facade/VoucherCustomerFacadeImpl.java index 937e8c53b7..7c291c58a3 100644 --- a/src/main/java/team/marco/voucher_management_system/facade/VoucherCustomerFacadeImpl.java +++ b/src/main/java/team/marco/voucher_management_system/facade/VoucherCustomerFacadeImpl.java @@ -1,7 +1,6 @@ package team.marco.voucher_management_system.facade; import java.util.List; -import java.util.Objects; import java.util.Optional; import java.util.UUID; import org.springframework.stereotype.Component; @@ -21,16 +20,15 @@ public VoucherCustomerFacadeImpl(VoucherRepository voucherRepository, CustomerRe } @Override - public boolean hasVoucher(String voucherId) { + public boolean hasVoucher(UUID voucherId) { return voucherRepository.findAll() .stream() .map(Voucher::getId) - .map(UUID::toString) - .anyMatch(id -> Objects.equals(id, voucherId)); + .anyMatch(voucherId::equals); } @Override - public boolean hasCustomer(String customerId) { + public boolean hasCustomer(UUID customerId) { Optional optionalCustomer = customerRepository.findById(customerId); return optionalCustomer.isPresent(); diff --git a/src/main/java/team/marco/voucher_management_system/repository/CustomerRepository.java b/src/main/java/team/marco/voucher_management_system/repository/CustomerRepository.java index 5de5403f15..e361dee002 100644 --- a/src/main/java/team/marco/voucher_management_system/repository/CustomerRepository.java +++ b/src/main/java/team/marco/voucher_management_system/repository/CustomerRepository.java @@ -2,6 +2,7 @@ import java.util.List; import java.util.Optional; +import java.util.UUID; import team.marco.voucher_management_system.model.Customer; public interface CustomerRepository { @@ -11,7 +12,7 @@ public interface CustomerRepository { int update(Customer customer); - Optional findById(String id); + Optional findById(UUID id); List findByName(String name); diff --git a/src/main/java/team/marco/voucher_management_system/repository/JdbcCustomerRepository.java b/src/main/java/team/marco/voucher_management_system/repository/JdbcCustomerRepository.java index 5e1f395c5a..9d28d62977 100644 --- a/src/main/java/team/marco/voucher_management_system/repository/JdbcCustomerRepository.java +++ b/src/main/java/team/marco/voucher_management_system/repository/JdbcCustomerRepository.java @@ -13,7 +13,6 @@ import java.util.Optional; import java.util.UUID; import org.springframework.dao.EmptyResultDataAccessException; -import org.springframework.jdbc.UncategorizedSQLException; import org.springframework.jdbc.core.RowMapper; import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; import org.springframework.stereotype.Repository; @@ -68,16 +67,16 @@ public int update(Customer customer) { } @Override - public Optional findById(String id) { + public Optional findById(UUID id) { try { Customer customer = jdbcTemplate.queryForObject( "SELECT * FROM customer" + " WHERE id = UUID_TO_BIN(:id)", - Collections.singletonMap("id", id.getBytes()), + Collections.singletonMap("id", id.toString().getBytes()), customerRowMapper); return Optional.ofNullable(customer); - } catch (EmptyResultDataAccessException | UncategorizedSQLException e) { + } catch (EmptyResultDataAccessException e) { return Optional.empty(); } } diff --git a/src/main/java/team/marco/voucher_management_system/repository/JdbcWalletRepository.java b/src/main/java/team/marco/voucher_management_system/repository/JdbcWalletRepository.java index cdd0b67e9c..3b6f8def67 100644 --- a/src/main/java/team/marco/voucher_management_system/repository/JdbcWalletRepository.java +++ b/src/main/java/team/marco/voucher_management_system/repository/JdbcWalletRepository.java @@ -1,7 +1,6 @@ package team.marco.voucher_management_system.repository; import java.io.ByteArrayInputStream; -import java.util.Collections; import java.util.List; import java.util.Map; import java.util.UUID; @@ -18,7 +17,7 @@ public JdbcWalletRepository(NamedParameterJdbcTemplate jdbcTemplate) { } @Override - public int link(String customerId, String voucherId) { + public int link(UUID customerId, UUID voucherId) { return jdbcTemplate.update( "INSERT INTO wallet(customer_id, voucher_id)" + " VALUES (UUID_TO_BIN(:customerId), UUID_TO_BIN(:voucherId))", @@ -26,7 +25,7 @@ public int link(String customerId, String voucherId) { } @Override - public int unlink(String customerId, String voucherId) { + public int unlink(UUID customerId, UUID voucherId) { return jdbcTemplate.update( "DELETE FROM wallet" + " WHERE (customer_id, voucher_id) = (UUID_TO_BIN(:customerId), UUID_TO_BIN(:voucherId))", @@ -34,30 +33,34 @@ public int unlink(String customerId, String voucherId) { } @Override - public List getVoucherIds(String customerId) { - return jdbcTemplate.queryForList( - "SELECT voucher_id FROM wallet" - + " WHERE customer_id = UUID_TO_BIN(:customerId)", - Collections.singletonMap("customerId", customerId), ByteArrayInputStream.class) - .stream() - .map(byteArray -> UUIDConverter.convert(byteArray.readAllBytes())) - .toList(); + public List getVoucherIds(UUID customerId) { + List voucherIds = jdbcTemplate.queryForList( + "SELECT voucher_id FROM wallet" + + " WHERE customer_id = UUID_TO_BIN(:customerId)", + walletToMap(customerId, customerId), + ByteArrayInputStream.class); + + return mapToUUID(voucherIds); } @Override - public List getCustomerIds(String voucherId) { - return jdbcTemplate.queryForList( - "SELECT customer_id FROM wallet" - + " WHERE voucher_id = UUID_TO_BIN(:voucherId)", - Collections.singletonMap("voucherId", voucherId), ByteArrayInputStream.class) - .stream() - .map(byteArray -> UUIDConverter.convert(byteArray.readAllBytes())) - .toList(); + public List getCustomerIds(UUID voucherId) { + return mapToUUID(jdbcTemplate.queryForList( + "SELECT customer_id FROM wallet" + + " WHERE voucher_id = UUID_TO_BIN(:voucherId)", + walletToMap(voucherId, voucherId), + ByteArrayInputStream.class)); } - private Map walletToMap(String customerId, String voucherId) { + private Map walletToMap(UUID customerId, UUID voucherId) { return Map.ofEntries( - Map.entry("customerId", customerId), - Map.entry("voucherId", voucherId)); + Map.entry("customerId", customerId.toString().getBytes()), + Map.entry("voucherId", voucherId.toString().getBytes())); + } + + private List mapToUUID(List ids) { + return ids.stream() + .map(byteArray -> UUIDConverter.convert(byteArray.readAllBytes())) + .toList(); } } diff --git a/src/main/java/team/marco/voucher_management_system/repository/WalletRepository.java b/src/main/java/team/marco/voucher_management_system/repository/WalletRepository.java index a0a2847e69..2bb57dfbd3 100644 --- a/src/main/java/team/marco/voucher_management_system/repository/WalletRepository.java +++ b/src/main/java/team/marco/voucher_management_system/repository/WalletRepository.java @@ -4,11 +4,11 @@ import java.util.UUID; public interface WalletRepository { - int link(String customerId, String voucherId); + int link(UUID customerId, UUID voucherId); - int unlink(String customerId, String voucherId); + int unlink(UUID customerId, UUID voucherId); - List getVoucherIds(String customerId); + List getVoucherIds(UUID customerId); - List getCustomerIds(String voucherId); + List getCustomerIds(UUID voucherId); } diff --git a/src/main/java/team/marco/voucher_management_system/service/CustomerService.java b/src/main/java/team/marco/voucher_management_system/service/CustomerService.java index 3a3a0669bb..38759fe7ff 100644 --- a/src/main/java/team/marco/voucher_management_system/service/CustomerService.java +++ b/src/main/java/team/marco/voucher_management_system/service/CustomerService.java @@ -2,6 +2,7 @@ import java.util.List; import java.util.Optional; +import java.util.UUID; import org.springframework.jdbc.datasource.lookup.DataSourceLookupFailureException; import org.springframework.stereotype.Service; import team.marco.voucher_management_system.model.Customer; @@ -29,7 +30,7 @@ public List getCustomers() { return customerRepository.findAll(); } - public void update(String id, String name) { + public void update(UUID id, String name) { Optional customerOptional = customerRepository.findById(id); Customer customer = customerOptional.orElseThrow(); @@ -43,7 +44,7 @@ public void update(String id, String name) { } } - public Customer findById(String id) { + public Customer findById(UUID id) { Optional customerOptional = customerRepository.findById(id); return customerOptional.orElseThrow(); diff --git a/src/main/java/team/marco/voucher_management_system/service/VoucherService.java b/src/main/java/team/marco/voucher_management_system/service/VoucherService.java index 1ee62c805c..856d8dec98 100644 --- a/src/main/java/team/marco/voucher_management_system/service/VoucherService.java +++ b/src/main/java/team/marco/voucher_management_system/service/VoucherService.java @@ -1,6 +1,8 @@ package team.marco.voucher_management_system.service; import java.util.List; +import java.util.Optional; +import java.util.UUID; import org.springframework.stereotype.Service; import team.marco.voucher_management_system.model.FixedAmountVoucher; import team.marco.voucher_management_system.model.PercentDiscountVoucher; @@ -28,4 +30,11 @@ public void createPercentDiscountVoucher(int percent) { public List getVouchers() { return voucherRepository.findAll(); } + + public Optional findById(UUID id) { + return voucherRepository.findAll() + .stream() + .filter(voucher -> voucher.isSameId(id)) + .findFirst(); + } } diff --git a/src/main/java/team/marco/voucher_management_system/service/WalletService.java b/src/main/java/team/marco/voucher_management_system/service/WalletService.java index 057f27cc6f..de55578502 100644 --- a/src/main/java/team/marco/voucher_management_system/service/WalletService.java +++ b/src/main/java/team/marco/voucher_management_system/service/WalletService.java @@ -19,33 +19,33 @@ public WalletService(WalletRepository walletRepository, VoucherCustomerFacade vo this.voucherCustomerFacade = voucherCustomerFacade; } - public void checkVoucherId(String voucherId) { + public void checkVoucherId(UUID voucherId) { if (!voucherCustomerFacade.hasVoucher(voucherId)) { throw new NoSuchElementException("ID가 일치하는 쿠폰이 존재하지 않습니다."); } } - public void checkCustomerId(String customerId) { + public void checkCustomerId(UUID customerId) { if (!voucherCustomerFacade.hasCustomer(customerId)) { throw new NoSuchElementException("ID가 일치하는 고객이 존재하지 않습니다."); } } - public int supplyVoucher(String customerId, String voucherId) { + public int supplyVoucher(UUID customerId, UUID voucherId) { return walletRepository.link(customerId, voucherId); } - public List findVouchersByCustomerId(String customerId) { + public List findVouchersByCustomerId(UUID customerId) { List voucherIds = walletRepository.getVoucherIds(customerId); return voucherCustomerFacade.getVouchers(voucherIds); } - public int returnVoucher(String customerId, String voucherId) { + public int returnVoucher(UUID customerId, UUID voucherId) { return walletRepository.unlink(customerId, voucherId); } - public List findCustomersByVoucherId(String voucherId) { + public List findCustomersByVoucherId(UUID voucherId) { List customerIds = walletRepository.getCustomerIds(voucherId); return voucherCustomerFacade.getCustomers(customerIds); diff --git a/src/main/java/team/marco/voucher_management_system/util/UUIDConverter.java b/src/main/java/team/marco/voucher_management_system/util/UUIDConverter.java index 17dc7a938b..4c071093b2 100644 --- a/src/main/java/team/marco/voucher_management_system/util/UUIDConverter.java +++ b/src/main/java/team/marco/voucher_management_system/util/UUIDConverter.java @@ -1,5 +1,6 @@ package team.marco.voucher_management_system.util; +import java.nio.BufferUnderflowException; import java.nio.ByteBuffer; import java.util.UUID; @@ -10,6 +11,14 @@ private UUIDConverter() { public static UUID convert(byte[] bytes) { ByteBuffer byteBuffer = ByteBuffer.wrap(bytes); - return new UUID(byteBuffer.getLong(), byteBuffer.getLong()); + try { + return new UUID(byteBuffer.getLong(), byteBuffer.getLong()); + } catch (BufferUnderflowException e) { + throw new IllegalArgumentException(e); + } + } + + public static UUID convert(String string) { + return convert(string.getBytes()); } } diff --git a/src/test/java/team/marco/voucher_management_system/repository/JdbcCustomerRepositoryTest.java b/src/test/java/team/marco/voucher_management_system/repository/JdbcCustomerRepositoryTest.java index 303d7f1c1f..73980ce45f 100644 --- a/src/test/java/team/marco/voucher_management_system/repository/JdbcCustomerRepositoryTest.java +++ b/src/test/java/team/marco/voucher_management_system/repository/JdbcCustomerRepositoryTest.java @@ -108,7 +108,7 @@ void testUpdate() { repository.update(generatedCustomer); // then - Optional optionalCustomer = repository.findById(generatedCustomer.getId().toString()); + Optional optionalCustomer = repository.findById(generatedCustomer.getId()); assertThat(optionalCustomer.isPresent()).isTrue(); @@ -132,7 +132,7 @@ void success() { repository.create(existCustomer); // when - Optional existOptionalCustomer = repository.findById(existCustomer.getId().toString()); + Optional existOptionalCustomer = repository.findById(existCustomer.getId()); // then assertThat(existOptionalCustomer.isPresent()).isTrue(); @@ -153,7 +153,7 @@ void failToNotExistId() { addTestCustomers(seed); // when - Optional existOptionalCustomer = repository.findById(notExistCustomer.getId().toString()); + Optional existOptionalCustomer = repository.findById(notExistCustomer.getId()); // then assertThat(existOptionalCustomer.isEmpty()).isTrue(); diff --git a/src/test/java/team/marco/voucher_management_system/repository/JdbcWalletRepositoryTest.java b/src/test/java/team/marco/voucher_management_system/repository/JdbcWalletRepositoryTest.java index d1e2c128cf..f0d2cf965b 100644 --- a/src/test/java/team/marco/voucher_management_system/repository/JdbcWalletRepositoryTest.java +++ b/src/test/java/team/marco/voucher_management_system/repository/JdbcWalletRepositoryTest.java @@ -67,7 +67,7 @@ void success() { Customer customer = addCustomer(0); // when - int count = walletRepository.link(customer.getId().toString(), voucher.getId().toString()); + int count = walletRepository.link(customer.getId(), voucher.getId()); // then assertThat(count).isEqualTo(1); @@ -80,11 +80,10 @@ void failToAlreadyExist() { Voucher voucher = addVoucher(); Customer customer = addCustomer(0); - walletRepository.link(customer.getId().toString(), voucher.getId().toString()); + walletRepository.link(customer.getId(), voucher.getId()); // when - ThrowingCallable targetMethod = () -> walletRepository.link( - customer.getId().toString(), voucher.getId().toString()); + ThrowingCallable targetMethod = () -> walletRepository.link(customer.getId(), voucher.getId()); // then assertThatExceptionOfType(DataIntegrityViolationException.class) @@ -102,10 +101,10 @@ void success() { Voucher voucher = addVoucher(); Customer customer = addCustomer(0); - walletRepository.link(customer.getId().toString(), voucher.getId().toString()); + walletRepository.link(customer.getId(), voucher.getId()); // when - int count = walletRepository.unlink(customer.getId().toString(), voucher.getId().toString()); + int count = walletRepository.unlink(customer.getId(), voucher.getId()); // then assertThat(count).isEqualTo(1); @@ -119,7 +118,7 @@ void failToNotExist() { Customer customer = addCustomer(0); // when - int count = walletRepository.unlink(customer.getId().toString(), voucher.getId().toString()); + int count = walletRepository.unlink(customer.getId(), voucher.getId()); // then assertThat(count).isEqualTo(0); @@ -133,10 +132,10 @@ void getVoucherIds() { UUID customerId = addCustomer(0).getId(); List voucherIds = List.of(addVoucher().getId(), addVoucher().getId(), addVoucher().getId()); - voucherIds.forEach(voucherId -> walletRepository.link(customerId.toString(), voucherId.toString())); + voucherIds.forEach(voucherId -> walletRepository.link(customerId, voucherId)); // when - List retrievedIds = walletRepository.getVoucherIds(customerId.toString()); + List retrievedIds = walletRepository.getVoucherIds(customerId); // then assertThat(retrievedIds).containsExactlyInAnyOrderElementsOf(voucherIds); @@ -153,11 +152,11 @@ void getCustomerIds() { UUID customerId = addCustomer(i).getId(); customerIds.add(customerId); - walletRepository.link(customerId.toString(), voucherId.toString()); + walletRepository.link(customerId, voucherId); } // when - List retrievedIds = walletRepository.getCustomerIds(voucherId.toString()); + List retrievedIds = walletRepository.getCustomerIds(voucherId); // then assertThat(retrievedIds).containsExactlyInAnyOrderElementsOf(customerIds); From 57984a2a1df68844730b9690b2e12c9f622906ce Mon Sep 17 00:00:00 2001 From: ASak1104 Date: Sun, 5 Nov 2023 21:07:00 +0900 Subject: [PATCH 22/73] =?UTF-8?q?chore=20:=20javafaker=20=EC=9D=98?= =?UTF-8?q?=EC=A1=B4=EC=84=B1=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 1 + 1 file changed, 1 insertion(+) diff --git a/build.gradle b/build.gradle index b8dd9725c6..8822fffc30 100644 --- a/build.gradle +++ b/build.gradle @@ -24,6 +24,7 @@ dependencies { implementation 'com.fasterxml.jackson.core:jackson-databind:2.15.2' implementation 'com.mysql:mysql-connector-j:8.1.0' testImplementation 'org.springframework.boot:spring-boot-starter-test' + testImplementation 'com.github.javafaker:javafaker:1.0.2' } tasks.named('test') { From 76a4da79f898e67631672308d32517f643594d80 Mon Sep 17 00:00:00 2001 From: ASak1104 Date: Sun, 5 Nov 2023 21:07:40 +0900 Subject: [PATCH 23/73] =?UTF-8?q?refactor=20:=20voucher=20=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C=20=EB=A1=9C=EC=A7=81=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../facade/VoucherCustomerFacadeImpl.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/main/java/team/marco/voucher_management_system/facade/VoucherCustomerFacadeImpl.java b/src/main/java/team/marco/voucher_management_system/facade/VoucherCustomerFacadeImpl.java index 7c291c58a3..392bda37e1 100644 --- a/src/main/java/team/marco/voucher_management_system/facade/VoucherCustomerFacadeImpl.java +++ b/src/main/java/team/marco/voucher_management_system/facade/VoucherCustomerFacadeImpl.java @@ -21,10 +21,9 @@ public VoucherCustomerFacadeImpl(VoucherRepository voucherRepository, CustomerRe @Override public boolean hasVoucher(UUID voucherId) { - return voucherRepository.findAll() - .stream() - .map(Voucher::getId) - .anyMatch(voucherId::equals); + Optional optionalVoucher = voucherRepository.findById(voucherId); + + return optionalVoucher.isPresent(); } @Override From 9a628522b46b8e0b6d147b8fbf3b6e3a1e0b2e96 Mon Sep 17 00:00:00 2001 From: ASak1104 Date: Sun, 5 Nov 2023 21:08:07 +0900 Subject: [PATCH 24/73] =?UTF-8?q?test=20:=20VoucherCCustomerFacade=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=BD=94=EB=93=9C=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../TestJdbcRepositoryConfiguration.java | 8 + .../facade/VoucherCustomerFacadeImplTest.java | 171 ++++++++++++++++++ 2 files changed, 179 insertions(+) create mode 100644 src/test/java/team/marco/voucher_management_system/facade/VoucherCustomerFacadeImplTest.java diff --git a/src/test/java/team/marco/voucher_management_system/configuration/TestJdbcRepositoryConfiguration.java b/src/test/java/team/marco/voucher_management_system/configuration/TestJdbcRepositoryConfiguration.java index ef048790f9..19ca1abe3b 100644 --- a/src/test/java/team/marco/voucher_management_system/configuration/TestJdbcRepositoryConfiguration.java +++ b/src/test/java/team/marco/voucher_management_system/configuration/TestJdbcRepositoryConfiguration.java @@ -4,6 +4,8 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; +import team.marco.voucher_management_system.facade.VoucherCustomerFacade; +import team.marco.voucher_management_system.facade.VoucherCustomerFacadeImpl; import team.marco.voucher_management_system.repository.JdbcCustomerRepository; import team.marco.voucher_management_system.repository.JdbcVoucherRepository; import team.marco.voucher_management_system.repository.JdbcWalletRepository; @@ -25,4 +27,10 @@ public JdbcCustomerRepository jdbcCustomerRepository(NamedParameterJdbcTemplate public JdbcWalletRepository jdbcWalletRepository(NamedParameterJdbcTemplate jdbcTemplate) { return new JdbcWalletRepository(jdbcTemplate); } + + @Bean + public VoucherCustomerFacade voucherCustomerFacade(JdbcVoucherRepository voucherRepository, + JdbcCustomerRepository customerRepository) { + return new VoucherCustomerFacadeImpl(voucherRepository, customerRepository); + } } diff --git a/src/test/java/team/marco/voucher_management_system/facade/VoucherCustomerFacadeImplTest.java b/src/test/java/team/marco/voucher_management_system/facade/VoucherCustomerFacadeImplTest.java new file mode 100644 index 0000000000..b32dbeee15 --- /dev/null +++ b/src/test/java/team/marco/voucher_management_system/facade/VoucherCustomerFacadeImplTest.java @@ -0,0 +1,171 @@ +package team.marco.voucher_management_system.facade; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.github.javafaker.Faker; +import java.util.List; +import java.util.UUID; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; +import team.marco.voucher_management_system.configuration.TestJdbcRepositoryConfiguration; +import team.marco.voucher_management_system.model.Customer; +import team.marco.voucher_management_system.model.FixedAmountVoucher; +import team.marco.voucher_management_system.model.Voucher; +import team.marco.voucher_management_system.repository.CustomerRepository; +import team.marco.voucher_management_system.repository.VoucherRepository; + +@TestInstance(TestInstance.Lifecycle.PER_CLASS) +@SpringJUnitConfig(TestJdbcRepositoryConfiguration.class) +class VoucherCustomerFacadeImplTest { + private static final String DELETE_FROM_VOUCHER = "DELETE FROM voucher;"; + private static final String DELETE_FROM_CUSTOMER = "DELETE FROM customer"; + private static final Faker faker = new Faker(); + + @Autowired + private JdbcTemplate jdbcTemplate; + @Autowired + private VoucherRepository voucherRepository; + @Autowired + private CustomerRepository customerRepository; + @Autowired + private VoucherCustomerFacade voucherCustomerFacade; + + @BeforeAll + @AfterEach + void truncateTable() { + jdbcTemplate.execute(DELETE_FROM_VOUCHER); + jdbcTemplate.execute(DELETE_FROM_CUSTOMER); + } + + @Nested + @DisplayName("Voucher 조회 테스트") + class TestHasVoucher { + @Test + @DisplayName("id가 일치하는 Voucher가 존재하면 true를 반환한다.") + void found() { + // given + Voucher voucher = generateVoucher(); + + voucherRepository.save(voucher); + + // when + boolean hasVoucher = voucherCustomerFacade.hasVoucher(voucher.getId()); + + // then + assertThat(hasVoucher).isTrue(); + } + + @Test + @DisplayName("id가 일치하는 Voucher가 없으면 false를 반환한다.") + void notFound() { + // given + Voucher voucher = generateVoucher(); + + // when + boolean hasVoucher = voucherCustomerFacade.hasVoucher(voucher.getId()); + + // then + assertThat(hasVoucher).isFalse(); + } + } + + @Nested + @DisplayName("Voucher 조회 테스트") + class TestHasCustomer { + @Test + @DisplayName("id가 일치하는 고객이 존재하면 true를 반환한다.") + void found() { + // given + Customer customer = generateCustomer(); + + customerRepository.create(customer); + + // when + boolean hasCustomer = voucherCustomerFacade.hasCustomer(customer.getId()); + + // then + assertThat(hasCustomer).isTrue(); + } + + @Test + @DisplayName("id가 일치하는 고객이 없으면 false를 반환한다.") + void notFound() { + // given + Customer customer = generateCustomer(); + + // when + boolean hasCustomer = voucherCustomerFacade.hasCustomer(customer.getId()); + + // then + assertThat(hasCustomer).isFalse(); + } + } + + @Test + @DisplayName("id 리스트에 있는 모든 Voucher를 조회할 수 있다.") + void testGetVouchers() { + // given + List vouchers = List.of( + generateVoucher(), + generateVoucher(), + generateVoucher()); + List voucherIds = vouchers.stream() + .map(Voucher::getId) + .toList(); + + vouchers.forEach(voucherRepository::save); + + // when + List retrievedVouchers = voucherCustomerFacade.getVouchers(voucherIds); + + // then + List retrievedVoucherIds = retrievedVouchers.stream() + .map(Voucher::getId) + .toList(); + + assertThat(retrievedVoucherIds).containsExactlyInAnyOrderElementsOf(voucherIds); + } + + @Test + @DisplayName("id 리스트에 있는 모든 고객을 조회할 수 있다.") + void testGetCustomers() { + // given + List customers = List.of( + generateCustomer(), + generateCustomer(), + generateCustomer()); + List customerIds = customers.stream() + .map(Customer::getId) + .toList(); + + customers.forEach(customerRepository::create); + + // when + List retrievedCustomers = voucherCustomerFacade.getCustomers(customerIds); + + // then + List retrievedCustomerIds = retrievedCustomers.stream() + .map(Customer::getId) + .toList(); + + assertThat(retrievedCustomerIds).containsExactlyInAnyOrderElementsOf(customerIds); + } + + private Voucher generateVoucher() { + return new FixedAmountVoucher(100); + } + + private Customer generateCustomer() { + String name = faker.name().name(); + String email = faker.internet().emailAddress(); + + return new Customer(name, email); + } +} From 2e34c0727c167cf7ca3a5c4e39efbde50b373667 Mon Sep 17 00:00:00 2001 From: ASak1104 Date: Sun, 5 Nov 2023 21:34:16 +0900 Subject: [PATCH 25/73] =?UTF-8?q?test=20:=20=EC=9D=B4=EB=A6=84=EA=B3=BC=20?= =?UTF-8?q?=EC=9D=B4=EB=A9=94=EC=9D=BC=20=EC=83=9D=EC=84=B1=EC=9D=84=20fak?= =?UTF-8?q?er=20=ED=81=B4=EB=9E=98=EC=8A=A4=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../facade/VoucherCustomerFacadeImplTest.java | 102 ++++----- .../model/BlacklistUserTest.java | 7 +- .../model/CustomerTest.java | 57 ++--- .../JdbcCustomerRepositoryTest.java | 194 +++++++++--------- .../repository/JdbcWalletRepositoryTest.java | 138 ++++++------- 5 files changed, 258 insertions(+), 240 deletions(-) diff --git a/src/test/java/team/marco/voucher_management_system/facade/VoucherCustomerFacadeImplTest.java b/src/test/java/team/marco/voucher_management_system/facade/VoucherCustomerFacadeImplTest.java index b32dbeee15..89feb25483 100644 --- a/src/test/java/team/marco/voucher_management_system/facade/VoucherCustomerFacadeImplTest.java +++ b/src/test/java/team/marco/voucher_management_system/facade/VoucherCustomerFacadeImplTest.java @@ -44,6 +44,56 @@ void truncateTable() { jdbcTemplate.execute(DELETE_FROM_CUSTOMER); } + @Test + @DisplayName("id 리스트에 있는 모든 Voucher를 조회할 수 있다.") + void testGetVouchers() { + // given + List vouchers = List.of( + generateVoucher(), + generateVoucher(), + generateVoucher()); + List voucherIds = vouchers.stream() + .map(Voucher::getId) + .toList(); + + vouchers.forEach(voucherRepository::save); + + // when + List retrievedVouchers = voucherCustomerFacade.getVouchers(voucherIds); + + // then + List retrievedVoucherIds = retrievedVouchers.stream() + .map(Voucher::getId) + .toList(); + + assertThat(retrievedVoucherIds).containsExactlyInAnyOrderElementsOf(voucherIds); + } + + @Test + @DisplayName("id 리스트에 있는 모든 고객을 조회할 수 있다.") + void testGetCustomers() { + // given + List customers = List.of( + generateCustomer(), + generateCustomer(), + generateCustomer()); + List customerIds = customers.stream() + .map(Customer::getId) + .toList(); + + customers.forEach(customerRepository::create); + + // when + List retrievedCustomers = voucherCustomerFacade.getCustomers(customerIds); + + // then + List retrievedCustomerIds = retrievedCustomers.stream() + .map(Customer::getId) + .toList(); + + assertThat(retrievedCustomerIds).containsExactlyInAnyOrderElementsOf(customerIds); + } + @Nested @DisplayName("Voucher 조회 테스트") class TestHasVoucher { @@ -108,62 +158,12 @@ void notFound() { } } - @Test - @DisplayName("id 리스트에 있는 모든 Voucher를 조회할 수 있다.") - void testGetVouchers() { - // given - List vouchers = List.of( - generateVoucher(), - generateVoucher(), - generateVoucher()); - List voucherIds = vouchers.stream() - .map(Voucher::getId) - .toList(); - - vouchers.forEach(voucherRepository::save); - - // when - List retrievedVouchers = voucherCustomerFacade.getVouchers(voucherIds); - - // then - List retrievedVoucherIds = retrievedVouchers.stream() - .map(Voucher::getId) - .toList(); - - assertThat(retrievedVoucherIds).containsExactlyInAnyOrderElementsOf(voucherIds); - } - - @Test - @DisplayName("id 리스트에 있는 모든 고객을 조회할 수 있다.") - void testGetCustomers() { - // given - List customers = List.of( - generateCustomer(), - generateCustomer(), - generateCustomer()); - List customerIds = customers.stream() - .map(Customer::getId) - .toList(); - - customers.forEach(customerRepository::create); - - // when - List retrievedCustomers = voucherCustomerFacade.getCustomers(customerIds); - - // then - List retrievedCustomerIds = retrievedCustomers.stream() - .map(Customer::getId) - .toList(); - - assertThat(retrievedCustomerIds).containsExactlyInAnyOrderElementsOf(customerIds); - } - private Voucher generateVoucher() { return new FixedAmountVoucher(100); } private Customer generateCustomer() { - String name = faker.name().name(); + String name = faker.name().firstName(); String email = faker.internet().emailAddress(); return new Customer(name, email); diff --git a/src/test/java/team/marco/voucher_management_system/model/BlacklistUserTest.java b/src/test/java/team/marco/voucher_management_system/model/BlacklistUserTest.java index 3f97920310..204c26b2f9 100644 --- a/src/test/java/team/marco/voucher_management_system/model/BlacklistUserTest.java +++ b/src/test/java/team/marco/voucher_management_system/model/BlacklistUserTest.java @@ -4,6 +4,7 @@ import static org.assertj.core.api.Assertions.assertThatNoException; import static org.hamcrest.MatcherAssert.assertThat; +import com.github.javafaker.Faker; import java.util.UUID; import org.assertj.core.api.ThrowableAssert.ThrowingCallable; import org.hamcrest.Matchers; @@ -11,12 +12,14 @@ import org.junit.jupiter.api.Test; class BlacklistUserTest { + private static final Faker faker = new Faker(); + @Test @DisplayName("이름이 빈 문자열이 아니면 생성에 성공해야한다.") void testSuccessCreation() { // given UUID id = UUID.randomUUID(); - String name = "test"; + String name = faker.name().name(); // when ThrowingCallable targetMethod = () -> new BlacklistUser(id, name); @@ -43,7 +46,7 @@ void testFailCreation() { @DisplayName("블랙리스트 사용자의 정보에는 id와 이름이 포함되어야 한다.") void testGetInfo() { UUID id = UUID.randomUUID(); - String name = "smith"; + String name = faker.name().name(); // when BlacklistUser blacklistUser = new BlacklistUser(id, name); diff --git a/src/test/java/team/marco/voucher_management_system/model/CustomerTest.java b/src/test/java/team/marco/voucher_management_system/model/CustomerTest.java index e7ccfcf2dc..6e14fb853c 100644 --- a/src/test/java/team/marco/voucher_management_system/model/CustomerTest.java +++ b/src/test/java/team/marco/voucher_management_system/model/CustomerTest.java @@ -7,6 +7,7 @@ import static org.hamcrest.Matchers.not; import static org.hamcrest.Matchers.notNullValue; +import com.github.javafaker.Faker; import java.time.LocalDateTime; import org.assertj.core.api.ThrowableAssert.ThrowingCallable; import org.junit.jupiter.api.DisplayName; @@ -16,9 +17,30 @@ class CustomerTest { private static final String INVALID_NAME_MESSAGE = "이름은 공백일 수 없습니다."; private static final String INVALID_EMAIL_MESSAGE = "이메일 형식이 올바르지 않습니다."; + private static final Faker faker = new Faker(); private Customer generateCustomer() { - return new Customer("test", "test@test.test"); + String name = faker.name().name(); + String email = faker.internet().emailAddress(); + + return new Customer(name, email); + } + + @Test + @DisplayName("로그인을 하면 lastLoginAt 필드 값이 바뀌어야 한다.") + void testLogin() { + // given + Customer customer = generateCustomer(); + LocalDateTime beforeLastLoginAt = customer.getLastLoginAt(); + + // when + customer.login(); + + // then + LocalDateTime afterLastLoginAt = customer.getLastLoginAt(); + + assertThat(afterLastLoginAt, notNullValue()); + assertThat(afterLastLoginAt, is(not(beforeLastLoginAt))); } @Nested @@ -28,8 +50,8 @@ class TestCreationName { @DisplayName("이름이 빈 문자열이 아니면 생성에 성공해야 한다.") void success() { // given - String name = "test"; - String email = "test@test.test"; + String name = faker.name().name(); + String email = faker.internet().emailAddress(); // when ThrowingCallable targetMethod = () -> new Customer(name, email); @@ -42,7 +64,7 @@ void success() { @DisplayName("이름이 빈 문자열이면 생성에 실패해야 한다.") void fail() { String name = ""; - String email = "test@test.test"; + String email = faker.internet().emailAddress(); // when ThrowingCallable targetMethod = () -> new Customer(name, email); @@ -60,8 +82,8 @@ class TestCreationEmail { @DisplayName("이메일이 형식에 맞으면 생성에 성공해야 한다.") void success() { // given - String name = "test"; - String email = "test@test.test"; + String name = faker.name().name(); + String email = faker.internet().emailAddress(); // when ThrowingCallable targetMethod = () -> new Customer(name, email); @@ -73,8 +95,8 @@ void success() { @Test @DisplayName("이메일이 형식에 맞지 않으면 생성에 실패해야 한다.") void fail() { - String name = "test"; - String email = "test"; + String name = faker.name().name(); + String email = faker.name().name(); // when ThrowingCallable targetMethod = () -> new Customer(name, email); @@ -93,7 +115,7 @@ class TestChangeName { void success() { // given Customer customer = generateCustomer(); - String name = "test2"; + String name = faker.name().name(); // when customer.changeName(name); @@ -118,21 +140,4 @@ void fail() { .withMessage(INVALID_NAME_MESSAGE); } } - - @Test - @DisplayName("로그인을 하면 lastLoginAt 필드 값이 바뀌어야 한다.") - void testLogin() { - // given - Customer customer = generateCustomer(); - LocalDateTime beforeLastLoginAt = customer.getLastLoginAt(); - - // when - customer.login(); - - // then - LocalDateTime afterLastLoginAt = customer.getLastLoginAt(); - - assertThat(afterLastLoginAt, notNullValue()); - assertThat(afterLastLoginAt, is(not(beforeLastLoginAt))); - } } diff --git a/src/test/java/team/marco/voucher_management_system/repository/JdbcCustomerRepositoryTest.java b/src/test/java/team/marco/voucher_management_system/repository/JdbcCustomerRepositoryTest.java index 73980ce45f..d31ecfbee3 100644 --- a/src/test/java/team/marco/voucher_management_system/repository/JdbcCustomerRepositoryTest.java +++ b/src/test/java/team/marco/voucher_management_system/repository/JdbcCustomerRepositoryTest.java @@ -3,9 +3,12 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; +import com.github.javafaker.Faker; import java.util.ArrayList; +import java.util.HashSet; import java.util.List; import java.util.Optional; +import java.util.Set; import java.util.UUID; import org.assertj.core.api.ThrowableAssert.ThrowingCallable; import org.junit.jupiter.api.AfterEach; @@ -25,6 +28,7 @@ @SpringJUnitConfig(TestJdbcRepositoryConfiguration.class) class JdbcCustomerRepositoryTest { private static final String DELETE_FROM_CUSTOMER = "DELETE FROM customer"; + private static final Faker faker = new Faker(); @Autowired private JdbcTemplate jdbcTemplate; @@ -37,40 +41,6 @@ void truncateTable() { jdbcTemplate.execute(DELETE_FROM_CUSTOMER); } - @Nested - @DisplayName("고객 추가 테스트") - class TestCreate { - @Test - @DisplayName("고객을 추가할 수 있어야 한다.") - void success() { - // given - Customer customer = generateCustomer(1000); - - // when - int count = repository.create(customer); - - // then - assertThat(count).isEqualTo(1); - } - - @Test - @DisplayName("동일한 이메일의 고객을 추가할 경우 예외가 발생한다.") - void failToDuplicateEmail() { - // given - Customer customer = new Customer("test1", "test@test.test"); - Customer duplicatedEmailCustomer = new Customer("test2", "test@test.test"); - - // when - int initInsertion = repository.create(customer); - - ThrowingCallable targetMethod = () -> repository.create(duplicatedEmailCustomer); - - // then - assertThat(initInsertion).isEqualTo(1); - assertThatExceptionOfType(DuplicateKeyException.class).isThrownBy(targetMethod); - } - } - @Test @DisplayName("추가한 사용자를 모두 찾을 수 있어야 한다.") void testFindAll() { @@ -98,8 +68,8 @@ void testFindAll() { @DisplayName("사용자의 이름을 수정할 수 있어야 한다.") void testUpdate() { // given - Customer generatedCustomer = generateCustomer(0); - String name = "changedName"; + Customer generatedCustomer = generateCustomer(); + String name = faker.name().name(); repository.create(generatedCustomer); @@ -118,62 +88,19 @@ void testUpdate() { assertThat(customer.getName()).isEqualTo(name); } - @Nested - @DisplayName("고객 id 조회 테스트") - class TestFindById { - @Test - @DisplayName("id가 일치하는 고객이 존재할 경우 조회할 수 있어야 한다.") - void success() { - // given - int seed = 100; - Customer existCustomer = generateCustomer(seed + 1); - - addTestCustomers(seed); - repository.create(existCustomer); - - // when - Optional existOptionalCustomer = repository.findById(existCustomer.getId()); - - // then - assertThat(existOptionalCustomer.isPresent()).isTrue(); - - Customer retrievedCustomer = existOptionalCustomer.get(); - - assertThat(retrievedCustomer).usingRecursiveComparison() - .isEqualTo(existCustomer); - } - - @Test - @DisplayName("id가 일치하는 고객이 없을 경우 예외를 발생해야 한다.") - void failToNotExistId() { - // given - int seed = 100; - Customer notExistCustomer = generateCustomer(seed + 1); - - addTestCustomers(seed); - - // when - Optional existOptionalCustomer = repository.findById(notExistCustomer.getId()); - - // then - assertThat(existOptionalCustomer.isEmpty()).isTrue(); - } - } - @Test @DisplayName("특정 문자를 포함하는 이름의 사용자를 모두 조회할 수 있어야 한다.") void testFindByName() { // given - int seed = 100; - String queryName = "5"; - List addedCustomers = addTestCustomers(seed); + String match = "t"; + List addedCustomers = addTestCustomers(10); // when - List customers = repository.findByName(queryName); + List customers = repository.findByName(match); // then List addedIds = addedCustomers.stream() - .filter(customer -> customer.getName().contains(queryName)) + .filter(customer -> isContain(customer.getName(), match)) .map(Customer::getId) .toList(); List customerIds = customers.stream() @@ -187,16 +114,15 @@ void testFindByName() { @DisplayName("특정 문자를 포함하는 이메일의 사용자를 모두 조회할 수 있어야 한다.") void testFindByEmail() { // given - int seed = 100; - String queryEmail = "st5"; - List addedCustomers = addTestCustomers(seed); + String match = "t"; + List addedCustomers = addTestCustomers(10); // when - List customers = repository.findByEmail(queryEmail); + List customers = repository.findByEmail(match); // then List addedIds = addedCustomers.stream() - .filter(customer -> customer.getEmail().contains(queryEmail)) + .filter(customer -> isContain(customer.getEmail(), match)) .map(Customer::getId) .toList(); List customerIds = customers.stream() @@ -206,23 +132,107 @@ void testFindByEmail() { assertThat(customerIds).containsExactlyInAnyOrderElementsOf(addedIds); } - private Customer generateCustomer(int seed) { - String name = String.format("testUser%d", seed); - String email = String.format("test%d@test.test", seed); + private Customer generateCustomer() { + String name = faker.name().firstName(); + String email = faker.internet().emailAddress(); return new Customer(name, email); } private List addTestCustomers(int count) { + Set emails = new HashSet<>(); List generatedCustomers = new ArrayList<>(); for (int i = 0; i < count; i++) { - Customer customer = generateCustomer(i); + Customer customer = generateCustomer(); + if (emails.contains(customer.getEmail())) { + continue; + } + + emails.add(customer.getEmail()); repository.create(customer); generatedCustomers.add(customer); } return generatedCustomers.stream().toList(); } + + private boolean isContain(String target, String match) { + return target.toLowerCase().contains(match.toLowerCase()); + } + + @Nested + @DisplayName("고객 추가 테스트") + class TestCreate { + @Test + @DisplayName("고객을 추가할 수 있어야 한다.") + void success() { + // given + Customer customer = generateCustomer(); + + // when + int count = repository.create(customer); + + // then + assertThat(count).isEqualTo(1); + } + + @Test + @DisplayName("동일한 이메일의 고객을 추가할 경우 예외가 발생한다.") + void failToDuplicateEmail() { + // given + Customer customer = new Customer("test1", "test@test.test"); + Customer duplicatedEmailCustomer = new Customer("test2", "test@test.test"); + + // when + int initInsertion = repository.create(customer); + + ThrowingCallable targetMethod = () -> repository.create(duplicatedEmailCustomer); + + // then + assertThat(initInsertion).isEqualTo(1); + assertThatExceptionOfType(DuplicateKeyException.class).isThrownBy(targetMethod); + } + } + + @Nested + @DisplayName("고객 id 조회 테스트") + class TestFindById { + @Test + @DisplayName("id가 일치하는 고객이 존재할 경우 조회할 수 있어야 한다.") + void success() { + // given + Customer existCustomer = generateCustomer(); + + addTestCustomers(10); + repository.create(existCustomer); + + // when + Optional existOptionalCustomer = repository.findById(existCustomer.getId()); + + // then + assertThat(existOptionalCustomer.isPresent()).isTrue(); + + Customer retrievedCustomer = existOptionalCustomer.get(); + + assertThat(retrievedCustomer).usingRecursiveComparison() + .isEqualTo(existCustomer); + } + + @Test + @DisplayName("id가 일치하는 고객이 없을 경우 예외를 발생해야 한다.") + void failToNotExistId() { + // given + Customer notExistCustomer = generateCustomer(); + + addTestCustomers(10); + + // when + Optional existOptionalCustomer = repository.findById(notExistCustomer.getId()); + + // then + assertThat(existOptionalCustomer.isEmpty()).isTrue(); + } + } } diff --git a/src/test/java/team/marco/voucher_management_system/repository/JdbcWalletRepositoryTest.java b/src/test/java/team/marco/voucher_management_system/repository/JdbcWalletRepositoryTest.java index f0d2cf965b..1374be073d 100644 --- a/src/test/java/team/marco/voucher_management_system/repository/JdbcWalletRepositoryTest.java +++ b/src/test/java/team/marco/voucher_management_system/repository/JdbcWalletRepositoryTest.java @@ -56,75 +56,6 @@ void truncateTables() { jdbcTemplate.execute(DELETE_FROM_CUSTOMER); } - @Nested - @DisplayName("고객 지갑 쿠폰 추가 테스트") - class TestLink { - @Test - @DisplayName("고객의 지갑에 쿠폰을 추가할 수 있다.") - void success() { - // given - Voucher voucher = addVoucher(); - Customer customer = addCustomer(0); - - // when - int count = walletRepository.link(customer.getId(), voucher.getId()); - - // then - assertThat(count).isEqualTo(1); - } - - @Test - @DisplayName("이미 추가된 쿠폰은 지갑에 추가될 수 없다.") - void failToAlreadyExist() { - // given - Voucher voucher = addVoucher(); - Customer customer = addCustomer(0); - - walletRepository.link(customer.getId(), voucher.getId()); - - // when - ThrowingCallable targetMethod = () -> walletRepository.link(customer.getId(), voucher.getId()); - - // then - assertThatExceptionOfType(DataIntegrityViolationException.class) - .isThrownBy(targetMethod); - } - } - - @Nested - @DisplayName("고객 지갑 쿠폰 반납 테스트") - class TestUnlink { - @Test - @DisplayName("고객의 지갑에 쿠폰을 반납할 수 있다.") - void success() { - // given - Voucher voucher = addVoucher(); - Customer customer = addCustomer(0); - - walletRepository.link(customer.getId(), voucher.getId()); - - // when - int count = walletRepository.unlink(customer.getId(), voucher.getId()); - - // then - assertThat(count).isEqualTo(1); - } - - @Test - @DisplayName("지갑에 없는 쿠폰은 지갑에 반납될 수 없다.") - void failToNotExist() { - // given - Voucher voucher = addVoucher(); - Customer customer = addCustomer(0); - - // when - int count = walletRepository.unlink(customer.getId(), voucher.getId()); - - // then - assertThat(count).isEqualTo(0); - } - } - @Test @DisplayName("특정 고객 지갑에 있는 모든 쿠폰을 조회할 수 있다.") void getVoucherIds() { @@ -199,4 +130,73 @@ private Customer addCustomer(int seed) { return customer; } + + @Nested + @DisplayName("고객 지갑 쿠폰 추가 테스트") + class TestLink { + @Test + @DisplayName("고객의 지갑에 쿠폰을 추가할 수 있다.") + void success() { + // given + Voucher voucher = addVoucher(); + Customer customer = addCustomer(0); + + // when + int count = walletRepository.link(customer.getId(), voucher.getId()); + + // then + assertThat(count).isEqualTo(1); + } + + @Test + @DisplayName("이미 추가된 쿠폰은 지갑에 추가될 수 없다.") + void failToAlreadyExist() { + // given + Voucher voucher = addVoucher(); + Customer customer = addCustomer(0); + + walletRepository.link(customer.getId(), voucher.getId()); + + // when + ThrowingCallable targetMethod = () -> walletRepository.link(customer.getId(), voucher.getId()); + + // then + assertThatExceptionOfType(DataIntegrityViolationException.class) + .isThrownBy(targetMethod); + } + } + + @Nested + @DisplayName("고객 지갑 쿠폰 반납 테스트") + class TestUnlink { + @Test + @DisplayName("고객의 지갑에 쿠폰을 반납할 수 있다.") + void success() { + // given + Voucher voucher = addVoucher(); + Customer customer = addCustomer(0); + + walletRepository.link(customer.getId(), voucher.getId()); + + // when + int count = walletRepository.unlink(customer.getId(), voucher.getId()); + + // then + assertThat(count).isEqualTo(1); + } + + @Test + @DisplayName("지갑에 없는 쿠폰은 지갑에 반납될 수 없다.") + void failToNotExist() { + // given + Voucher voucher = addVoucher(); + Customer customer = addCustomer(0); + + // when + int count = walletRepository.unlink(customer.getId(), voucher.getId()); + + // then + assertThat(count).isEqualTo(0); + } + } } From eb891a90c86d0106d673cfef9e3a4ead1f435d1a Mon Sep 17 00:00:00 2001 From: ASak1104 Date: Sun, 5 Nov 2023 22:53:37 +0900 Subject: [PATCH 26/73] =?UTF-8?q?refactor=20:=20=ED=95=84=EC=9A=94=20?= =?UTF-8?q?=EC=97=86=EB=8A=94=20=EC=83=9D=EC=84=B1=EC=9E=90=20=EC=A0=9C?= =?UTF-8?q?=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../voucher_management_system/model/FixedAmountVoucher.java | 6 ------ .../model/PercentDiscountVoucher.java | 6 ------ 2 files changed, 12 deletions(-) diff --git a/src/main/java/team/marco/voucher_management_system/model/FixedAmountVoucher.java b/src/main/java/team/marco/voucher_management_system/model/FixedAmountVoucher.java index 5242b062c8..ed66e6f71f 100644 --- a/src/main/java/team/marco/voucher_management_system/model/FixedAmountVoucher.java +++ b/src/main/java/team/marco/voucher_management_system/model/FixedAmountVoucher.java @@ -19,12 +19,6 @@ public FixedAmountVoucher(int amount) { this.amount = amount; } - public FixedAmountVoucher(UUID id, int amount) { - super(id); - - this.amount = amount; - } - public FixedAmountVoucher(UUID id, int amount, LocalDateTime createAt) { super(id); diff --git a/src/main/java/team/marco/voucher_management_system/model/PercentDiscountVoucher.java b/src/main/java/team/marco/voucher_management_system/model/PercentDiscountVoucher.java index 5f77fa4488..0af8b1378d 100644 --- a/src/main/java/team/marco/voucher_management_system/model/PercentDiscountVoucher.java +++ b/src/main/java/team/marco/voucher_management_system/model/PercentDiscountVoucher.java @@ -19,12 +19,6 @@ public PercentDiscountVoucher(int percent) { this.percent = percent; } - public PercentDiscountVoucher(UUID id, int percent) { - super(id); - - this.percent = percent; - } - public PercentDiscountVoucher(UUID id, int percent, LocalDateTime createAt) { super(id); From c71699755c14bfe0e096998c42e941d4b8483a63 Mon Sep 17 00:00:00 2001 From: ASak1104 Date: Sun, 5 Nov 2023 22:54:01 +0900 Subject: [PATCH 27/73] =?UTF-8?q?feat=20:=20Console=20=EC=9C=A0=ED=8B=B8?= =?UTF-8?q?=20close=20=EB=A9=94=EC=84=9C=EB=93=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../VoucherManagementSystemApplication.java | 13 ++------- .../util/Console.java | 29 +++++++++++++++++-- 2 files changed, 29 insertions(+), 13 deletions(-) diff --git a/src/main/java/team/marco/voucher_management_system/VoucherManagementSystemApplication.java b/src/main/java/team/marco/voucher_management_system/VoucherManagementSystemApplication.java index 08313424ea..f5184fa798 100644 --- a/src/main/java/team/marco/voucher_management_system/VoucherManagementSystemApplication.java +++ b/src/main/java/team/marco/voucher_management_system/VoucherManagementSystemApplication.java @@ -1,28 +1,21 @@ package team.marco.voucher_management_system; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.context.properties.ConfigurationPropertiesScan; import org.springframework.context.ApplicationContext; -import org.springframework.core.env.Environment; import team.marco.voucher_management_system.console_app.application.CommandMainApplication; +import team.marco.voucher_management_system.util.Console; @SpringBootApplication @ConfigurationPropertiesScan public class VoucherManagementSystemApplication { - private static final Logger logger = LoggerFactory.getLogger(VoucherManagementSystemApplication.class); - public static void main(String[] args) { ApplicationContext context = SpringApplication.run(VoucherManagementSystemApplication.class, args); - Environment environment = context.getEnvironment(); - - logger.info("Program start (profile: {})", environment.getActiveProfiles()[0]); - CommandMainApplication application = context.getBean(CommandMainApplication.class); + application.run(); - logger.info("Program exit"); + Console.close(); } } diff --git a/src/main/java/team/marco/voucher_management_system/util/Console.java b/src/main/java/team/marco/voucher_management_system/util/Console.java index 339e6a73c8..7a11a7b852 100644 --- a/src/main/java/team/marco/voucher_management_system/util/Console.java +++ b/src/main/java/team/marco/voucher_management_system/util/Console.java @@ -7,7 +7,7 @@ import java.util.Objects; public final class Console { - private static final BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); + private static BufferedReader reader; private Console() { // Don't let anyone instantiate this class. @@ -19,7 +19,7 @@ public static String readString() { System.out.println(); if (Objects.isNull(input)) { - throw new RuntimeException("입력 과정에서 오류가 발생했습니다."); + throw new UncheckedIOException(new IOException("입력 과정에서 오류가 발생했습니다.")); } return input; @@ -31,7 +31,7 @@ public static int readInt() { private static String readLine() { try { - return reader.readLine(); + return getInstance().readLine(); } catch (IOException e) { throw new UncheckedIOException(e); } @@ -40,4 +40,27 @@ private static String readLine() { public static void print(Object object) { System.out.println(object + System.lineSeparator()); // thanks to SH, IJ } + + public static void close() { + if (reader != null) { + closeReader(); + + reader = null; + } + } + + private static BufferedReader getInstance() { + if (reader == null) { + reader = new BufferedReader(new InputStreamReader(System.in)); + } + return reader; + } + + private static void closeReader() { + try { + reader.close(); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } } From 6dd746f1a789a168cf2be81593fc30dbe0a5a436 Mon Sep 17 00:00:00 2001 From: ASak1104 Date: Sun, 5 Nov 2023 22:54:18 +0900 Subject: [PATCH 28/73] =?UTF-8?q?test=20:=20Console=20=EC=9C=A0=ED=8B=B8?= =?UTF-8?q?=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=BD=94=EB=93=9C=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../util/ConsoleTest.java | 129 ++++++++++++++++++ 1 file changed, 129 insertions(+) create mode 100644 src/test/java/team/marco/voucher_management_system/util/ConsoleTest.java diff --git a/src/test/java/team/marco/voucher_management_system/util/ConsoleTest.java b/src/test/java/team/marco/voucher_management_system/util/ConsoleTest.java new file mode 100644 index 0000000000..75df9e2c67 --- /dev/null +++ b/src/test/java/team/marco/voucher_management_system/util/ConsoleTest.java @@ -0,0 +1,129 @@ +package team.marco.voucher_management_system.util; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatException; + +import com.github.javafaker.Faker; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; +import java.io.UncheckedIOException; +import org.assertj.core.api.ThrowableAssert.ThrowingCallable; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.springframework.test.annotation.DirtiesContext; + +@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD) +class ConsoleTest { + private final static Faker faker = new Faker(); + private final static String EOF = "\u001a"; + + private final ByteArrayOutputStream outputStreamCaptor = new ByteArrayOutputStream(); + + @BeforeEach + void setup() { + System.setOut(new PrintStream(outputStreamCaptor)); + } + + @AfterEach + void cleanup() { + Console.close(); + } + + @Nested + @DisplayName("readString() 테스트") + class TestReadString { + @Test + @DisplayName("콘솔 입력을 읽을 수 있다.") + void normal() { + // given + String input = faker.address().country(); + + setStdin(input); + + // when + String readString = Console.readString(); + + // then + assertThat(readString).isEqualTo(input); + } + + @Test + @DisplayName("EOF 발생 시 예외를 발생한다.") + void EOF() { + // given + setStdin(EOF); + + Console.readString(); // skip EOF character + + // when + ThrowingCallable target = Console::readString; + + // then + assertThatException().isThrownBy(target) + .isInstanceOf(UncheckedIOException.class) + .withMessageContaining("입력 과정에서 오류가 발생했습니다."); + } + } + + @Nested + @DisplayName("readInt() 테스트") + class TestReadInt { + @Test + @DisplayName("콘솔 입력을 숫자로 변환할 수 있다.") + void normal() { + // given + String input = faker.number().digit(); + + setStdin(input); + + // when + int readInt = Console.readInt(); + + // then + assertThat(readInt).isEqualTo(Integer.parseInt(input)); + } + + @Test + @DisplayName("숫자로 변환할 수 없을 시 예외를 발생한다.") + void numberFormatException() { + // given + String input = faker.name().firstName(); + + setStdin(input); + + // when + ThrowingCallable target = Console::readInt; + + // then + assertThatException().isThrownBy(target) + .isInstanceOf(NumberFormatException.class); + } + } + + @Test + @DisplayName("사용자 입력을 콘솔로 출력할 수 있다.") + void testPrint() { + // given + String userOutput = faker.name().firstName(); + + // when + Console.print(userOutput); + + // then + String stdout = getStdout(); + + assertThat(stdout).startsWith(userOutput); + } + + private void setStdin(String input) { + System.setIn(new ByteArrayInputStream(input.getBytes())); + } + + private String getStdout() { + return outputStreamCaptor.toString(); + } +} From 5ca617d3125e4b9ee136f4e970a13e0cc64737c6 Mon Sep 17 00:00:00 2001 From: ASak1104 Date: Sun, 5 Nov 2023 23:14:43 +0900 Subject: [PATCH 29/73] =?UTF-8?q?fix=20:=20=EB=AC=B8=EC=9E=90=EC=97=B4?= =?UTF-8?q?=EC=9D=84=20=EB=B3=80=ED=99=98=20=EB=B0=A9=EB=B2=95=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../marco/voucher_management_system/util/UUIDConverter.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/team/marco/voucher_management_system/util/UUIDConverter.java b/src/main/java/team/marco/voucher_management_system/util/UUIDConverter.java index 4c071093b2..b63925a2a7 100644 --- a/src/main/java/team/marco/voucher_management_system/util/UUIDConverter.java +++ b/src/main/java/team/marco/voucher_management_system/util/UUIDConverter.java @@ -14,11 +14,11 @@ public static UUID convert(byte[] bytes) { try { return new UUID(byteBuffer.getLong(), byteBuffer.getLong()); } catch (BufferUnderflowException e) { - throw new IllegalArgumentException(e); + throw new IllegalArgumentException("UUID는 16Byte여야 합니다."); } } public static UUID convert(String string) { - return convert(string.getBytes()); + return UUID.fromString(string); } } From f4a2123e6417d6a36d5f47084f60e5a497c86f79 Mon Sep 17 00:00:00 2001 From: ASak1104 Date: Sun, 5 Nov 2023 23:14:56 +0900 Subject: [PATCH 30/73] =?UTF-8?q?test=20:=20UUIDConverter=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=EC=BD=94=EB=93=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../util/UUIDConverterTest.java | 67 +++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 src/test/java/team/marco/voucher_management_system/util/UUIDConverterTest.java diff --git a/src/test/java/team/marco/voucher_management_system/util/UUIDConverterTest.java b/src/test/java/team/marco/voucher_management_system/util/UUIDConverterTest.java new file mode 100644 index 0000000000..e8ad306045 --- /dev/null +++ b/src/test/java/team/marco/voucher_management_system/util/UUIDConverterTest.java @@ -0,0 +1,67 @@ +package team.marco.voucher_management_system.util; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; + +import java.nio.ByteBuffer; +import java.util.UUID; +import org.assertj.core.api.ThrowableAssert.ThrowingCallable; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +class UUIDConverterTest { + @Nested + @DisplayName("byte[] to UUID 테스트") + class TestConvertBytes { + @Test + void success() { + // given + UUID originId = UUID.randomUUID(); + byte[] uuidBytes = convertUUIDToBytes(originId); + + // when + UUID uuid = UUIDConverter.convert(uuidBytes); + + // then + assertThat(uuid).isEqualTo(originId); + } + + @Test + @DisplayName("16Byte 보다 작을 경우 예외를 발생한다.") + void underflowException() { + // given + byte[] uuidBytes = new byte[8]; + + // when + ThrowingCallable target = () -> UUIDConverter.convert(uuidBytes); + + // then + assertThatIllegalArgumentException().isThrownBy(target) + .withMessage("UUID는 16Byte여야 합니다."); + } + } + + @Test + @DisplayName("string to UUID 테스트") + void testConvertString() { + // given + UUID originId = UUID.randomUUID(); + String uuidString = originId.toString(); + + // when + UUID uuid = UUIDConverter.convert(uuidString); + + // then + assertThat(uuid).isEqualTo(originId); + } + + private byte[] convertUUIDToBytes(UUID uuid) { + ByteBuffer byteBuffer = ByteBuffer.wrap(new byte[16]); + + byteBuffer.putLong(uuid.getMostSignificantBits()); + byteBuffer.putLong(uuid.getLeastSignificantBits()); + + return byteBuffer.array(); + } +} From a1b92b574d6e4ffa94379d0d2135e05c94416302 Mon Sep 17 00:00:00 2001 From: ASak1104 Date: Mon, 6 Nov 2023 00:32:28 +0900 Subject: [PATCH 31/73] =?UTF-8?q?refactor=20:=20=EB=A9=94=EC=84=9C?= =?UTF-8?q?=EB=93=9C=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../repository/JdbcCustomerRepository.java | 23 +++++++++++-------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/src/main/java/team/marco/voucher_management_system/repository/JdbcCustomerRepository.java b/src/main/java/team/marco/voucher_management_system/repository/JdbcCustomerRepository.java index 9d28d62977..1e8b25a152 100644 --- a/src/main/java/team/marco/voucher_management_system/repository/JdbcCustomerRepository.java +++ b/src/main/java/team/marco/voucher_management_system/repository/JdbcCustomerRepository.java @@ -100,15 +100,7 @@ public List findByEmail(String email) { } private Map customerToMap(Customer customer) { - Map customerFields = new HashMap<>() { - { - put("id", customer.getId().toString().getBytes()); - put("name", customer.getName()); - put("email", customer.getEmail()); - put("lastLoginAt", null); - put("createdAt", Timestamp.valueOf(customer.getCreatedAt())); - } - }; + Map customerFields = getCustomerFields(customer); if (!Objects.isNull(customer.getLastLoginAt())) { customerFields.put("lastLoginAt", Timestamp.valueOf(customer.getLastLoginAt())); @@ -117,6 +109,19 @@ private Map customerToMap(Customer customer) { return customerFields; } + private Map getCustomerFields(Customer customer) { + Map customerFields = new HashMap<>() { + }; + + customerFields.put("id", customer.getId().toString().getBytes()); + customerFields.put("name", customer.getName()); + customerFields.put("email", customer.getEmail()); + customerFields.put("lastLoginAt", null); + customerFields.put("createdAt", Timestamp.valueOf(customer.getCreatedAt())); + + return customerFields; + } + private String withWildCards(String word) { return MessageFormat.format("%{0}%", word); } From 174d918ca2879c0f83c3c28620fb50c26e19d512 Mon Sep 17 00:00:00 2001 From: ASak1104 Date: Mon, 6 Nov 2023 00:32:46 +0900 Subject: [PATCH 32/73] =?UTF-8?q?fix=20:=20=EB=B6=88=ED=95=84=EC=9A=94?= =?UTF-8?q?=ED=95=9C=20=EC=98=88=EC=99=B8=20=EC=B2=98=EB=A6=AC=20=EC=A0=9C?= =?UTF-8?q?=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../console_app/application/CommandWalletApplication.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/team/marco/voucher_management_system/console_app/application/CommandWalletApplication.java b/src/main/java/team/marco/voucher_management_system/console_app/application/CommandWalletApplication.java index 985483743c..04ca39a833 100644 --- a/src/main/java/team/marco/voucher_management_system/console_app/application/CommandWalletApplication.java +++ b/src/main/java/team/marco/voucher_management_system/console_app/application/CommandWalletApplication.java @@ -4,7 +4,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.dao.DuplicateKeyException; -import org.springframework.dao.EmptyResultDataAccessException; import org.springframework.jdbc.UncategorizedSQLException; import org.springframework.stereotype.Component; import team.marco.voucher_management_system.console_app.controller.ConsoleWalletController; @@ -50,7 +49,7 @@ private void executeCommand(int userInput) { } catch (DuplicateKeyException e) { logger.error(e.toString()); Console.print("이미 존재하는 쿠폰입니다."); - } catch (EmptyResultDataAccessException | NoSuchElementException | UncategorizedSQLException e) { + } catch (NoSuchElementException | UncategorizedSQLException e) { logger.error(e.toString()); Console.print("존재하지 않는 ID 입니다."); } From e931e5547c5c568171b2d2eddc60ee15533733d6 Mon Sep 17 00:00:00 2001 From: ASak1104 Date: Mon, 6 Nov 2023 00:33:27 +0900 Subject: [PATCH 33/73] =?UTF-8?q?feat=20:=20VoucherRepository=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. 삭제 기능 2. 생성 일자에 대한 조회 --- .../model/Voucher.java | 4 ++ .../repository/JSONFileVoucherRepository.java | 19 ++++++++ .../repository/JdbcVoucherRepository.java | 48 ++++++++++++++----- .../repository/MemoryVoucherRepository.java | 19 ++++++++ .../repository/VoucherRepository.java | 5 ++ 5 files changed, 84 insertions(+), 11 deletions(-) diff --git a/src/main/java/team/marco/voucher_management_system/model/Voucher.java b/src/main/java/team/marco/voucher_management_system/model/Voucher.java index e0e7f68e16..eae392ac2f 100644 --- a/src/main/java/team/marco/voucher_management_system/model/Voucher.java +++ b/src/main/java/team/marco/voucher_management_system/model/Voucher.java @@ -33,6 +33,10 @@ public boolean isSameType(VoucherType voucherType) { return getType() == voucherType; } + public boolean isCreatedBetween(LocalDateTime from, LocalDateTime to) { + return !(createAt.isBefore(from) | createAt.isAfter(to)); + } + public final UUID getId() { return id; } diff --git a/src/main/java/team/marco/voucher_management_system/repository/JSONFileVoucherRepository.java b/src/main/java/team/marco/voucher_management_system/repository/JSONFileVoucherRepository.java index 6479844e81..135b2dfe13 100644 --- a/src/main/java/team/marco/voucher_management_system/repository/JSONFileVoucherRepository.java +++ b/src/main/java/team/marco/voucher_management_system/repository/JSONFileVoucherRepository.java @@ -5,6 +5,7 @@ import java.io.File; import java.io.IOException; import java.io.UncheckedIOException; +import java.time.LocalDateTime; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -58,6 +59,17 @@ public void save(Voucher voucher) { voucherMap.put(voucher.getId(), voucher); } + @Override + public int deleteById(UUID id) { + if (!voucherMap.containsKey(id)) { + return 0; + } + + voucherMap.remove(id); + + return 1; + } + @Override public List findAll() { return voucherMap.values() @@ -82,6 +94,13 @@ public List findByType(VoucherType voucherType) { .toList(); } + @Override + public List findByCreateAt(LocalDateTime from, LocalDateTime to) { + return findAll().stream() + .filter(voucher -> voucher.isCreatedBetween(from, to)) + .toList(); + } + @Override public void destroy() { try { diff --git a/src/main/java/team/marco/voucher_management_system/repository/JdbcVoucherRepository.java b/src/main/java/team/marco/voucher_management_system/repository/JdbcVoucherRepository.java index b833b6c70b..f546b0fb9d 100644 --- a/src/main/java/team/marco/voucher_management_system/repository/JdbcVoucherRepository.java +++ b/src/main/java/team/marco/voucher_management_system/repository/JdbcVoucherRepository.java @@ -2,16 +2,16 @@ import java.sql.ResultSet; import java.sql.SQLException; +import java.sql.Timestamp; import java.time.LocalDateTime; import java.util.Collections; import java.util.List; import java.util.Map; +import java.util.NoSuchElementException; import java.util.Optional; import java.util.UUID; import org.springframework.context.annotation.Profile; -import org.springframework.dao.DataAccessResourceFailureException; import org.springframework.dao.EmptyResultDataAccessException; -import org.springframework.jdbc.UncategorizedSQLException; import org.springframework.jdbc.core.RowMapper; import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; import org.springframework.stereotype.Repository; @@ -49,14 +49,22 @@ private static Voucher mapToVoucher(ResultSet resultSet, int ignored) throws SQL @Override public void save(Voucher voucher) { int updateCount = jdbcTemplate.update( - "INSERT INTO voucher(id, type, data) VALUES (UUID_TO_BIN(:id), :type, :data)", + "INSERT INTO voucher(id, type, data, created_at)" + + " VALUES (UUID_TO_BIN(:id), :type, :data, :created_at)", voucherToMap(voucher)); - if (updateCount != 1) { - throw new DataAccessResourceFailureException("Insert query not committed"); + if (updateCount == 0) { + throw new NoSuchElementException("Insert fail voucher=%s".formatted(voucher)); } } + @Override + public int deleteById(UUID id) { + return jdbcTemplate.update( + "DELETE FROM voucher WHERE id = UUID_TO_BIN(:id)", + Collections.singletonMap("id", id.toString().getBytes())); + } + @Override public List findAll() { return jdbcTemplate.query("SELECT * FROM voucher", voucherRowMapper); @@ -66,13 +74,12 @@ public List findAll() { public Optional findById(UUID id) { try { Voucher voucher = jdbcTemplate.queryForObject( - "SELECT * FROM voucher" - + " WHERE id = UUID_TO_BIN(:id)", + "SELECT * FROM voucher WHERE id = UUID_TO_BIN(:id)", Collections.singletonMap("id", id.toString().getBytes()), voucherRowMapper); return Optional.ofNullable(voucher); - } catch (EmptyResultDataAccessException | UncategorizedSQLException e) { + } catch (EmptyResultDataAccessException e) { return Optional.empty(); } } @@ -80,16 +87,35 @@ public Optional findById(UUID id) { @Override public List findByType(VoucherType voucherType) { return jdbcTemplate.query( - "SELECT * FROM voucher" - + " WHERE type = :type", + "SELECT * FROM voucher WHERE type = :type", Collections.singletonMap("type", voucherType.toString()), voucherRowMapper); } + @Override + public List findByCreateAt(LocalDateTime from, LocalDateTime to) { + return jdbcTemplate.query( + "SELECT * FROM voucher WHERE created_at BETWEEN :from AND :to", + mapToTimestamp(from, to), + voucherRowMapper); + } + private Map voucherToMap(Voucher voucher) { + Timestamp createAt = Timestamp.valueOf(voucher.getCreateAt()); + return Map.ofEntries( Map.entry("id", voucher.getId().toString().getBytes()), Map.entry("type", voucher.getType().toString()), - Map.entry("data", voucher.getData())); + Map.entry("data", voucher.getData()), + Map.entry("created_at", createAt)); + } + + private Map mapToTimestamp(LocalDateTime from, LocalDateTime to) { + Timestamp createdFrom = Timestamp.valueOf(from); + Timestamp createdTo = Timestamp.valueOf(to); + + return Map.ofEntries( + Map.entry("from", createdFrom), + Map.entry("to", createdTo)); } } diff --git a/src/main/java/team/marco/voucher_management_system/repository/MemoryVoucherRepository.java b/src/main/java/team/marco/voucher_management_system/repository/MemoryVoucherRepository.java index 1616d005b9..7c09c3c3ff 100644 --- a/src/main/java/team/marco/voucher_management_system/repository/MemoryVoucherRepository.java +++ b/src/main/java/team/marco/voucher_management_system/repository/MemoryVoucherRepository.java @@ -1,5 +1,6 @@ package team.marco.voucher_management_system.repository; +import java.time.LocalDateTime; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -20,6 +21,17 @@ public void save(Voucher voucher) { voucherMap.put(voucher.getId(), voucher); } + @Override + public int deleteById(UUID id) { + if (!voucherMap.containsKey(id)) { + return 0; + } + + voucherMap.remove(id); + + return 1; + } + @Override public List findAll() { return voucherMap.values() @@ -43,4 +55,11 @@ public List findByType(VoucherType voucherType) { .filter(voucher -> voucher.isSameType(voucherType)) .toList(); } + + @Override + public List findByCreateAt(LocalDateTime from, LocalDateTime to) { + return findAll().stream() + .filter(voucher -> voucher.isCreatedBetween(from, to)) + .toList(); + } } diff --git a/src/main/java/team/marco/voucher_management_system/repository/VoucherRepository.java b/src/main/java/team/marco/voucher_management_system/repository/VoucherRepository.java index fe071867f7..e0efbfcdc9 100644 --- a/src/main/java/team/marco/voucher_management_system/repository/VoucherRepository.java +++ b/src/main/java/team/marco/voucher_management_system/repository/VoucherRepository.java @@ -1,5 +1,6 @@ package team.marco.voucher_management_system.repository; +import java.time.LocalDateTime; import java.util.List; import java.util.Optional; import java.util.UUID; @@ -9,9 +10,13 @@ public interface VoucherRepository { void save(Voucher voucher); + int deleteById(UUID id); + List findAll(); Optional findById(UUID id); List findByType(VoucherType voucherType); + + List findByCreateAt(LocalDateTime from, LocalDateTime to); } From 34cb1189818b2f1fa078112cc1675242766e44ae Mon Sep 17 00:00:00 2001 From: ASak1104 Date: Mon, 6 Nov 2023 00:34:36 +0900 Subject: [PATCH 34/73] =?UTF-8?q?test=20:=20=EC=82=AD=EC=A0=9C=20&=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=20=EC=9D=BC=EC=9E=90=20=EC=A1=B0=ED=9A=8C=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../repository/VoucherRepositoryTest.java | 106 ++++++++++++++---- 1 file changed, 85 insertions(+), 21 deletions(-) diff --git a/src/test/java/team/marco/voucher_management_system/repository/VoucherRepositoryTest.java b/src/test/java/team/marco/voucher_management_system/repository/VoucherRepositoryTest.java index 6f5c64cf6b..7739181990 100644 --- a/src/test/java/team/marco/voucher_management_system/repository/VoucherRepositoryTest.java +++ b/src/test/java/team/marco/voucher_management_system/repository/VoucherRepositoryTest.java @@ -1,18 +1,14 @@ package team.marco.voucher_management_system.repository; +import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatNoException; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.empty; -import static org.hamcrest.Matchers.is; -import static org.hamcrest.Matchers.not; -import static org.hamcrest.Matchers.notNullValue; +import java.time.LocalDateTime; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Optional; import java.util.UUID; -import org.assertj.core.api.Assertions; import org.assertj.core.api.ThrowableAssert.ThrowingCallable; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; @@ -22,12 +18,12 @@ import team.marco.voucher_management_system.type_enum.VoucherType; abstract class VoucherRepositoryTest { - protected abstract VoucherRepository getRepository(); - protected Voucher generateVoucher() { return new FixedAmountVoucher(10_000); } + protected abstract VoucherRepository getRepository(); + @Test @DisplayName("Repository는 null일 수 없다.") void testNonNullRepository() { @@ -37,11 +33,11 @@ void testNonNullRepository() { VoucherRepository repository = getRepository(); // then - assertThat(repository, notNullValue()); + assertThat(repository).isNotNull(); } @Test - @DisplayName("Voucher 추가가 가능해야 한다.") + @DisplayName("바우처 추가가 가능해야 한다.") void testSave() { // given VoucherRepository repository = getRepository(); @@ -54,8 +50,44 @@ void testSave() { assertThatNoException().isThrownBy(targetMethod); } + @Nested + @DisplayName("id로 바우처 삭제 테스트") + class TestDeleteById { + @Test + @DisplayName("id가 일치하는 바우처가 존재할 경우 삭제할 수 있다.") + void success() { + // given + VoucherRepository repository = getRepository(); + Voucher generatedVoucher = generateVoucher(); + UUID id = generatedVoucher.getId(); + + repository.save(generatedVoucher); + + // when + int count = repository.deleteById(id); + + // then + assertThat(count).isEqualTo(1); + } + + @Test + @DisplayName("id가 일치하는 바우처가 없을 경우 숫자 0을 반환한다.") + void notExist() { + // given + VoucherRepository repository = getRepository(); + Voucher notExistVoucher = generateVoucher(); + UUID notExistVoucherId = notExistVoucher.getId(); + + // when + int count = repository.deleteById(notExistVoucherId); + + // then + assertThat(count).isEqualTo(0); + } + } + @Test - @DisplayName("추가한 모든 Voucher를 조회할 수 있어야 한다.") + @DisplayName("추가한 모든 바우처를 조회할 수 있어야 한다.") void testFindAll() { // given VoucherRepository repository = getRepository(); @@ -77,16 +109,16 @@ void testFindAll() { .map(Voucher::getId) .toList(); - assertThat(retrievedIds, not(empty())); + assertThat(retrievedIds).isNotEmpty(); - Assertions.assertThat(retrievedIds).containsExactlyInAnyOrderElementsOf(generatedIds); + assertThat(retrievedIds).containsExactlyInAnyOrderElementsOf(generatedIds); } @Nested - @DisplayName("Voucher id 조회 테스트") + @DisplayName("바우처 id 조회 테스트") class TestFindById { @Test - @DisplayName("id가 일치하는 Voucher가 존재할 경우 조회할 수 있어야 한다.") + @DisplayName("id가 일치하는 바우처가 존재할 경우 조회할 수 있어야 한다.") void success() { // given VoucherRepository repository = getRepository(); @@ -99,15 +131,15 @@ void success() { Optional optionalVoucher = repository.findById(id); // then - assertThat(optionalVoucher.isEmpty(), is(false)); + assertThat(optionalVoucher).isNotEmpty(); Voucher voucher = optionalVoucher.get(); - assertThat(voucher.getId(), is(id)); + assertThat(voucher.getId()).isEqualTo(id); } @Test - @DisplayName("id가 일치하는 고객이 없을 경우 빈 optional 객체를 반환한다.") + @DisplayName("id가 일치하는 바우처 없을 경우 빈 optional 객체를 반환한다.") void emptyVoucher() { // given VoucherRepository repository = getRepository(); @@ -118,12 +150,12 @@ void emptyVoucher() { Optional optionalVoucher = repository.findById(notExistVoucherId); // then - assertThat(optionalVoucher.isEmpty(), is(true)); + assertThat(optionalVoucher).isEmpty(); } } @Test - @DisplayName("type이 일치하는 Voucher를 모두 반환한다.") + @DisplayName("type이 일치하는 바우처를 모두 반환한다.") void testFindByType() { // given VoucherRepository repository = getRepository(); @@ -149,6 +181,38 @@ void testFindByType() { .map(Math::toIntExact) .toList(); - Assertions.assertThat(counts).containsExactlyElementsOf(expectedCounts); + assertThat(counts).containsExactlyElementsOf(expectedCounts); + } + + @Test + @DisplayName("생성 일자를 기준으로 조회할 수 있다.") + void testFindByCreateAt() { + // given + VoucherRepository repository = getRepository(); + List vouchers = List.of( + generateVoucher(), + generateVoucher(), + generateVoucher(), + generateVoucher(), + generateVoucher()); + + vouchers.forEach(repository::save); + + LocalDateTime from = vouchers.get(1).getCreateAt(); + LocalDateTime to = vouchers.get(3).getCreateAt(); + + // when + List retrievedVouchers = repository.findByCreateAt(from, to); + + // then + List retrievedIds = retrievedVouchers.stream() + .map(Voucher::getId) + .toList(); + List expectedIds = vouchers.stream() + .filter(voucher -> voucher.isCreatedBetween(from, to)) + .map(Voucher::getId) + .toList(); + + assertThat(retrievedIds).containsExactlyInAnyOrderElementsOf(expectedIds); } } From 882020a46423c06e88728639fabd9ed50668e9c6 Mon Sep 17 00:00:00 2001 From: ASak1104 Date: Mon, 6 Nov 2023 00:37:00 +0900 Subject: [PATCH 35/73] =?UTF-8?q?refactor=20:=20=EB=B6=88=ED=95=84?= =?UTF-8?q?=EC=9A=94=ED=95=9C=20=EC=98=88=EC=99=B8=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../console_app/application/CommandWalletApplication.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/team/marco/voucher_management_system/console_app/application/CommandWalletApplication.java b/src/main/java/team/marco/voucher_management_system/console_app/application/CommandWalletApplication.java index 04ca39a833..ad6b61aa14 100644 --- a/src/main/java/team/marco/voucher_management_system/console_app/application/CommandWalletApplication.java +++ b/src/main/java/team/marco/voucher_management_system/console_app/application/CommandWalletApplication.java @@ -4,7 +4,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.dao.DuplicateKeyException; -import org.springframework.jdbc.UncategorizedSQLException; import org.springframework.stereotype.Component; import team.marco.voucher_management_system.console_app.controller.ConsoleWalletController; import team.marco.voucher_management_system.type_enum.WalletCommandType; @@ -49,7 +48,7 @@ private void executeCommand(int userInput) { } catch (DuplicateKeyException e) { logger.error(e.toString()); Console.print("이미 존재하는 쿠폰입니다."); - } catch (NoSuchElementException | UncategorizedSQLException e) { + } catch (NoSuchElementException e) { logger.error(e.toString()); Console.print("존재하지 않는 ID 입니다."); } From 3341f3917f6d92915523e5c5672e50bdec50b2d2 Mon Sep 17 00:00:00 2001 From: ASak1104 Date: Mon, 6 Nov 2023 00:47:26 +0900 Subject: [PATCH 36/73] =?UTF-8?q?test=20:=20=EB=B0=94=EC=9A=B0=EC=B2=98=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=20=EB=8D=B0=EC=9D=B4=ED=84=B0=EB=A5=BC=20?= =?UTF-8?q?=EB=9E=9C=EB=8D=A4=EC=9C=BC=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../model/FixedAmountVoucherTest.java | 4 +++- .../model/PercentDiscountVoucherTest.java | 4 +++- .../repository/VoucherRepositoryTest.java | 16 +++++++++++++++- 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/src/test/java/team/marco/voucher_management_system/model/FixedAmountVoucherTest.java b/src/test/java/team/marco/voucher_management_system/model/FixedAmountVoucherTest.java index f34cc50d30..81904197af 100644 --- a/src/test/java/team/marco/voucher_management_system/model/FixedAmountVoucherTest.java +++ b/src/test/java/team/marco/voucher_management_system/model/FixedAmountVoucherTest.java @@ -7,6 +7,7 @@ import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.lessThanOrEqualTo; +import com.github.javafaker.Faker; import org.assertj.core.api.ThrowableAssert.ThrowingCallable; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -16,6 +17,7 @@ class FixedAmountVoucherTest extends VoucherTest { private static final VoucherType FIXED_VOUCHER_TYPE = VoucherType.FIXED; private static final int MAXIMUM_AMOUNT = (int) 1e9; private static final int MINIMUM_AMOUNT = 1; + private static final Faker faker = new Faker(); @Override protected VoucherType getTargetType() { @@ -24,7 +26,7 @@ protected VoucherType getTargetType() { @Override protected int generateValidData() { - return (MAXIMUM_AMOUNT + MINIMUM_AMOUNT) / 2; + return faker.number().numberBetween(MINIMUM_AMOUNT, MAXIMUM_AMOUNT); } @Override diff --git a/src/test/java/team/marco/voucher_management_system/model/PercentDiscountVoucherTest.java b/src/test/java/team/marco/voucher_management_system/model/PercentDiscountVoucherTest.java index fcbe3661d1..de2d39d9d4 100644 --- a/src/test/java/team/marco/voucher_management_system/model/PercentDiscountVoucherTest.java +++ b/src/test/java/team/marco/voucher_management_system/model/PercentDiscountVoucherTest.java @@ -7,6 +7,7 @@ import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.lessThanOrEqualTo; +import com.github.javafaker.Faker; import org.assertj.core.api.ThrowableAssert.ThrowingCallable; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -16,6 +17,7 @@ class PercentDiscountVoucherTest extends VoucherTest { private static final VoucherType PERCENT_VOUCHER_TYPE = VoucherType.PERCENT; private static final int MAXIMUM_PERCENT = 100; private static final int MINIMUM_PERCENT = 1; + private static final Faker faker = new Faker(); @Override protected VoucherType getTargetType() { @@ -24,7 +26,7 @@ protected VoucherType getTargetType() { @Override protected int generateValidData() { - return (MAXIMUM_PERCENT + MINIMUM_PERCENT) / 2; + return faker.number().numberBetween(MINIMUM_PERCENT, MAXIMUM_PERCENT); } @Override diff --git a/src/test/java/team/marco/voucher_management_system/repository/VoucherRepositoryTest.java b/src/test/java/team/marco/voucher_management_system/repository/VoucherRepositoryTest.java index 7739181990..35e12bd982 100644 --- a/src/test/java/team/marco/voucher_management_system/repository/VoucherRepositoryTest.java +++ b/src/test/java/team/marco/voucher_management_system/repository/VoucherRepositoryTest.java @@ -3,6 +3,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatNoException; +import com.github.javafaker.Faker; import java.time.LocalDateTime; import java.util.ArrayList; import java.util.Arrays; @@ -14,12 +15,25 @@ import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import team.marco.voucher_management_system.model.FixedAmountVoucher; +import team.marco.voucher_management_system.model.PercentDiscountVoucher; import team.marco.voucher_management_system.model.Voucher; import team.marco.voucher_management_system.type_enum.VoucherType; abstract class VoucherRepositoryTest { + private static final int MAXIMUM_AMOUNT = (int) 1e9; + private static final int MINIMUM_AMOUNT = 1; + private static final int MAXIMUM_PERCENT = 100; + private static final int MINIMUM_PERCENT = 1; + private static final Faker faker = new Faker(); + protected Voucher generateVoucher() { - return new FixedAmountVoucher(10_000); + int randomNumber = faker.random().nextInt(1, 100); + + if (randomNumber % 2 == 0) { + return new PercentDiscountVoucher(faker.random().nextInt(MINIMUM_PERCENT, MAXIMUM_PERCENT)); + } + + return new FixedAmountVoucher(faker.random().nextInt(MINIMUM_AMOUNT, MAXIMUM_AMOUNT)); } protected abstract VoucherRepository getRepository(); From efa55f050c9f7fa5a400cd2d61d68bdb259f7fc6 Mon Sep 17 00:00:00 2001 From: ASak1104 Date: Mon, 6 Nov 2023 01:10:28 +0900 Subject: [PATCH 37/73] =?UTF-8?q?test=20:=20=EC=83=9D=EC=84=B1=20=EA=B8=B0?= =?UTF-8?q?=EA=B0=84=20=EC=A1=B0=ED=9A=8C=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../model/VoucherTest.java | 54 ++++++++++++++----- 1 file changed, 40 insertions(+), 14 deletions(-) diff --git a/src/test/java/team/marco/voucher_management_system/model/VoucherTest.java b/src/test/java/team/marco/voucher_management_system/model/VoucherTest.java index 4fe3c547e1..4e7fb5f3cf 100644 --- a/src/test/java/team/marco/voucher_management_system/model/VoucherTest.java +++ b/src/test/java/team/marco/voucher_management_system/model/VoucherTest.java @@ -1,14 +1,13 @@ package team.marco.voucher_management_system.model; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.containsString; -import static org.hamcrest.Matchers.instanceOf; -import static org.hamcrest.Matchers.is; -import static org.hamcrest.Matchers.notNullValue; +import static org.assertj.core.api.Assertions.assertThat; import java.text.NumberFormat; +import java.time.LocalDateTime; import java.util.Arrays; +import java.util.List; import java.util.UUID; +import java.util.stream.Stream; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; @@ -31,8 +30,8 @@ void testGetType() { VoucherType voucherType = voucher.getType(); // then - assertThat(voucherType, notNullValue()); - assertThat(voucherType, instanceOf(VoucherType.class)); + assertThat(voucherType).isNotNull(); + assertThat(voucherType).isInstanceOf(VoucherType.class); } @Test @@ -46,7 +45,7 @@ void testGetData() { int voucherData = voucher.getData(); // then - assertThat(voucherData, is(initData)); + assertThat(voucherData).isEqualTo(initData); } @Test @@ -62,8 +61,8 @@ void testGetInfo() { // then UUID id = voucher.getId(); - assertThat(voucherInfo, containsString(id.toString())); - assertThat(voucherInfo, containsString(NumberFormat.getIntegerInstance().format(initData))); + assertThat(voucherInfo).contains(id.toString()); + assertThat(voucherInfo).contains(NumberFormat.getIntegerInstance().format(initData)); } @Nested @@ -80,7 +79,7 @@ void isSameId() { boolean isSameId = voucher.isSameId(voucherId); // then - assertThat(isSameId, is(true)); + assertThat(isSameId).isTrue(); } @Test @@ -95,7 +94,7 @@ void isNotSameId() { boolean isSameId = voucher.isSameId(voucherId); // then - assertThat(isSameId, is(false)); + assertThat(isSameId).isFalse(); } } @@ -113,7 +112,7 @@ void isSameType() { boolean isSameType = voucher.isSameType(targetType); // then - assertThat(isSameType, is(true)); + assertThat(isSameType).isTrue(); } @Test @@ -131,7 +130,34 @@ void isNotSameType() { boolean isSameType = voucher.isSameType(otherType); // then - assertThat(isSameType, is(false)); + assertThat(isSameType).isFalse(); } } + + @Test + void isCreatedBetween() { + // given + List vouchers = List.of( + generateVoucher(generateValidData()), + generateVoucher(generateValidData()), + generateVoucher(generateValidData()), + generateVoucher(generateValidData()), + generateVoucher(generateValidData())); + + LocalDateTime from = vouchers.get(1).getCreateAt(); + LocalDateTime to = vouchers.get(3).getCreateAt(); + + // when + List actualVoucherIds = vouchers.stream() + .filter(voucher -> voucher.isCreatedBetween(from, to)) + .map(Voucher::getId) + .toList(); + + // then + List expectedVoucherIds = Stream.of(vouchers.get(1), vouchers.get(2), vouchers.get(3)) + .map(Voucher::getId) + .toList(); + + assertThat(actualVoucherIds).isEqualTo(expectedVoucherIds); + } } From fc7fbd14ed1c5b49e2b54f3da9b09ec9486b297d Mon Sep 17 00:00:00 2001 From: ASak1104 Date: Mon, 6 Nov 2023 03:26:48 +0900 Subject: [PATCH 38/73] =?UTF-8?q?feat=20:=20=EB=B0=94=EC=9A=B0=EC=B2=98=20?= =?UTF-8?q?api=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/VoucherService.java | 39 +++++++-- .../web_app/controller/VoucherController.java | 85 +++++++++++++++++++ .../web_app/dto/CreateVoucherRequest.java | 8 ++ src/main/resources/application.yml | 3 + 4 files changed, 129 insertions(+), 6 deletions(-) create mode 100644 src/main/java/team/marco/voucher_management_system/web_app/controller/VoucherController.java create mode 100644 src/main/java/team/marco/voucher_management_system/web_app/dto/CreateVoucherRequest.java diff --git a/src/main/java/team/marco/voucher_management_system/service/VoucherService.java b/src/main/java/team/marco/voucher_management_system/service/VoucherService.java index 856d8dec98..55edc4e59d 100644 --- a/src/main/java/team/marco/voucher_management_system/service/VoucherService.java +++ b/src/main/java/team/marco/voucher_management_system/service/VoucherService.java @@ -1,5 +1,6 @@ package team.marco.voucher_management_system.service; +import java.time.LocalDateTime; import java.util.List; import java.util.Optional; import java.util.UUID; @@ -8,6 +9,8 @@ import team.marco.voucher_management_system.model.PercentDiscountVoucher; import team.marco.voucher_management_system.model.Voucher; import team.marco.voucher_management_system.repository.VoucherRepository; +import team.marco.voucher_management_system.type_enum.VoucherType; +import team.marco.voucher_management_system.web_app.dto.CreateVoucherRequest; @Service public class VoucherService { @@ -17,14 +20,20 @@ public VoucherService(VoucherRepository voucherRepository) { this.voucherRepository = voucherRepository; } - public void createFixedAmountVoucher(int amount) { + public Voucher createFixedAmountVoucher(int amount) { Voucher voucher = new FixedAmountVoucher(amount); + voucherRepository.save(voucher); + + return voucher; } - public void createPercentDiscountVoucher(int percent) { + public Voucher createPercentDiscountVoucher(int percent) { Voucher voucher = new PercentDiscountVoucher(percent); + voucherRepository.save(voucher); + + return voucher; } public List getVouchers() { @@ -32,9 +41,27 @@ public List getVouchers() { } public Optional findById(UUID id) { - return voucherRepository.findAll() - .stream() - .filter(voucher -> voucher.isSameId(id)) - .findFirst(); + return voucherRepository.findById(id); + } + + public List findByCreateAt(LocalDateTime from, LocalDateTime to) { + return voucherRepository.findByCreateAt(from, to); + } + + public Voucher create(CreateVoucherRequest createVoucherRequest) { + return switch (createVoucherRequest.type()) { + case FIXED -> createFixedAmountVoucher(createVoucherRequest.data()); + case PERCENT -> createPercentDiscountVoucher(createVoucherRequest.data()); + }; + } + + public boolean deleteById(UUID id) { + int deleteCount = voucherRepository.deleteById(id); + + return deleteCount != 0; + } + + public List findByType(VoucherType voucherType) { + return voucherRepository.findByType(voucherType); } } diff --git a/src/main/java/team/marco/voucher_management_system/web_app/controller/VoucherController.java b/src/main/java/team/marco/voucher_management_system/web_app/controller/VoucherController.java new file mode 100644 index 0000000000..54bef4122d --- /dev/null +++ b/src/main/java/team/marco/voucher_management_system/web_app/controller/VoucherController.java @@ -0,0 +1,85 @@ +package team.marco.voucher_management_system.web_app.controller; + +import java.time.LocalDateTime; +import java.util.List; +import java.util.Optional; +import java.util.UUID; +import org.springframework.format.annotation.DateTimeFormat; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; +import team.marco.voucher_management_system.model.Voucher; +import team.marco.voucher_management_system.service.VoucherService; +import team.marco.voucher_management_system.type_enum.VoucherType; +import team.marco.voucher_management_system.web_app.dto.CreateVoucherRequest; + +@Controller +public class VoucherController { + private static final String DATE_PATTERN = "yyyy-MM-dd HH:mm:ss"; + + private final VoucherService voucherService; + + public VoucherController(VoucherService voucherService) { + this.voucherService = voucherService; + } + + @GetMapping("/vouchers") + @ResponseBody + public List findAll() { + return voucherService.getVouchers(); + } + + @PostMapping("/vouchers") + @ResponseBody + public ResponseEntity create(CreateVoucherRequest createVoucherRequest) { + Voucher voucher = voucherService.create(createVoucherRequest); + + return ResponseEntity.ok(voucher); + } + + @GetMapping("/vouchers/{id}") + @ResponseBody + public ResponseEntity findById(@PathVariable("id") UUID id) { + Optional optionalVoucher = voucherService.findById(id); + + return optionalVoucher.map(ResponseEntity::ok) + .orElse(ResponseEntity.noContent() + .build()); + } + + @DeleteMapping("/vouchers/{id}") + @ResponseBody + public ResponseEntity delete(@PathVariable("id") UUID id) { + boolean isDeleted = voucherService.deleteById(id); + + if (!isDeleted) { + return ResponseEntity.noContent() + .build(); + } + + return ResponseEntity.ok() + .build(); + } + + @GetMapping("/vouchers/createdAt") + @ResponseBody + public List findByCreateAt(@RequestParam("from") + @DateTimeFormat(pattern = DATE_PATTERN) + LocalDateTime from, + @RequestParam("to") + @DateTimeFormat(pattern = DATE_PATTERN) + LocalDateTime to) { + return voucherService.findByCreateAt(from, to); + } + + @GetMapping("/vouchers/type/{type}") + @ResponseBody + public List findByType(@PathVariable("type") VoucherType voucherType) { + return voucherService.findByType(voucherType); + } +} diff --git a/src/main/java/team/marco/voucher_management_system/web_app/dto/CreateVoucherRequest.java b/src/main/java/team/marco/voucher_management_system/web_app/dto/CreateVoucherRequest.java new file mode 100644 index 0000000000..5ba23eea1e --- /dev/null +++ b/src/main/java/team/marco/voucher_management_system/web_app/dto/CreateVoucherRequest.java @@ -0,0 +1,8 @@ +package team.marco.voucher_management_system.web_app.dto; + +import team.marco.voucher_management_system.type_enum.VoucherType; + +public record CreateVoucherRequest( + VoucherType type, + int data) { +} diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 12e3e24d8d..5777c5645b 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -9,6 +9,9 @@ spring: username: root password: +server: + port: 8080 + file: path: blacklist: src/main/resources/blacklist.csv From 98b5430257174c22d3f7bb2d6ec44b98abe52d9e Mon Sep 17 00:00:00 2001 From: ASak1104 Date: Mon, 6 Nov 2023 06:10:10 +0900 Subject: [PATCH 39/73] =?UTF-8?q?chore=20:=20xml=20dataformat=20=EC=9D=98?= =?UTF-8?q?=EC=A1=B4=EC=84=B1=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 1 + 1 file changed, 1 insertion(+) diff --git a/build.gradle b/build.gradle index 8822fffc30..b7e292c343 100644 --- a/build.gradle +++ b/build.gradle @@ -22,6 +22,7 @@ dependencies { implementation 'org.springframework.boot:spring-boot-starter-web' implementation 'org.springframework.boot:spring-boot-starter-jdbc' implementation 'com.fasterxml.jackson.core:jackson-databind:2.15.2' + implementation 'com.fasterxml.jackson.dataformat:jackson-dataformat-xml:2.15.2' implementation 'com.mysql:mysql-connector-j:8.1.0' testImplementation 'org.springframework.boot:spring-boot-starter-test' testImplementation 'com.github.javafaker:javafaker:1.0.2' From 8c7aada9548b91acc39d1e526d5746003750b5d3 Mon Sep 17 00:00:00 2001 From: ASak1104 Date: Mon, 6 Nov 2023 06:10:40 +0900 Subject: [PATCH 40/73] =?UTF-8?q?feat=20:=20xml=20response=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../web_app/controller/VoucherController.java | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/src/main/java/team/marco/voucher_management_system/web_app/controller/VoucherController.java b/src/main/java/team/marco/voucher_management_system/web_app/controller/VoucherController.java index 54bef4122d..a95e8809d8 100644 --- a/src/main/java/team/marco/voucher_management_system/web_app/controller/VoucherController.java +++ b/src/main/java/team/marco/voucher_management_system/web_app/controller/VoucherController.java @@ -5,20 +5,22 @@ import java.util.Optional; import java.util.UUID; import org.springframework.format.annotation.DateTimeFormat; +import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; -import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.RestController; import team.marco.voucher_management_system.model.Voucher; import team.marco.voucher_management_system.service.VoucherService; import team.marco.voucher_management_system.type_enum.VoucherType; import team.marco.voucher_management_system.web_app.dto.CreateVoucherRequest; -@Controller +@RestController +@RequestMapping(produces = {MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE}) public class VoucherController { private static final String DATE_PATTERN = "yyyy-MM-dd HH:mm:ss"; @@ -29,13 +31,11 @@ public VoucherController(VoucherService voucherService) { } @GetMapping("/vouchers") - @ResponseBody public List findAll() { return voucherService.getVouchers(); } @PostMapping("/vouchers") - @ResponseBody public ResponseEntity create(CreateVoucherRequest createVoucherRequest) { Voucher voucher = voucherService.create(createVoucherRequest); @@ -43,7 +43,6 @@ public ResponseEntity create(CreateVoucherRequest createVoucherRequest) } @GetMapping("/vouchers/{id}") - @ResponseBody public ResponseEntity findById(@PathVariable("id") UUID id) { Optional optionalVoucher = voucherService.findById(id); @@ -53,7 +52,6 @@ public ResponseEntity findById(@PathVariable("id") UUID id) { } @DeleteMapping("/vouchers/{id}") - @ResponseBody public ResponseEntity delete(@PathVariable("id") UUID id) { boolean isDeleted = voucherService.deleteById(id); @@ -67,7 +65,6 @@ public ResponseEntity delete(@PathVariable("id") UUID id) { } @GetMapping("/vouchers/createdAt") - @ResponseBody public List findByCreateAt(@RequestParam("from") @DateTimeFormat(pattern = DATE_PATTERN) LocalDateTime from, @@ -78,7 +75,6 @@ public List findByCreateAt(@RequestParam("from") } @GetMapping("/vouchers/type/{type}") - @ResponseBody public List findByType(@PathVariable("type") VoucherType voucherType) { return voucherService.findByType(voucherType); } From f262bebc7a178500eefa90e43272a69ef0895d27 Mon Sep 17 00:00:00 2001 From: ASak1104 Date: Mon, 6 Nov 2023 06:11:45 +0900 Subject: [PATCH 41/73] =?UTF-8?q?feat=20:=20=EC=95=A0=ED=94=8C=EB=A6=AC?= =?UTF-8?q?=EC=BC=80=EC=9D=B4=EC=85=98=20=EC=84=A0=ED=83=9D=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 현재 기술적인 문제를 해결하지 못 해 모두 최상단에 위치해있음 추후 개선 필요 --- .../ConsoleApplication.java | 22 +++++++++++++ .../VoucherManagementSystemApplication.java | 31 +++++++++++++------ .../WebApplication.java | 13 ++++++++ 3 files changed, 56 insertions(+), 10 deletions(-) create mode 100644 src/main/java/team/marco/voucher_management_system/ConsoleApplication.java create mode 100644 src/main/java/team/marco/voucher_management_system/WebApplication.java diff --git a/src/main/java/team/marco/voucher_management_system/ConsoleApplication.java b/src/main/java/team/marco/voucher_management_system/ConsoleApplication.java new file mode 100644 index 0000000000..0b00f428cb --- /dev/null +++ b/src/main/java/team/marco/voucher_management_system/ConsoleApplication.java @@ -0,0 +1,22 @@ +package team.marco.voucher_management_system; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.WebApplicationType; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.context.properties.ConfigurationPropertiesScan; +import org.springframework.context.ConfigurableApplicationContext; +import team.marco.voucher_management_system.console_app.application.CommandMainApplication; + +@SpringBootApplication +@ConfigurationPropertiesScan +public class ConsoleApplication { + public static void main(String[] args) { + SpringApplication springApplication = new SpringApplication(ConsoleApplication.class); + springApplication.setWebApplicationType(WebApplicationType.NONE); + + ConfigurableApplicationContext context = springApplication.run(args); + CommandMainApplication application = context.getBean(CommandMainApplication.class); + + application.run(); + } +} diff --git a/src/main/java/team/marco/voucher_management_system/VoucherManagementSystemApplication.java b/src/main/java/team/marco/voucher_management_system/VoucherManagementSystemApplication.java index f5184fa798..e3fc83934b 100644 --- a/src/main/java/team/marco/voucher_management_system/VoucherManagementSystemApplication.java +++ b/src/main/java/team/marco/voucher_management_system/VoucherManagementSystemApplication.java @@ -1,21 +1,32 @@ package team.marco.voucher_management_system; -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.boot.context.properties.ConfigurationPropertiesScan; -import org.springframework.context.ApplicationContext; -import team.marco.voucher_management_system.console_app.application.CommandMainApplication; import team.marco.voucher_management_system.util.Console; -@SpringBootApplication -@ConfigurationPropertiesScan public class VoucherManagementSystemApplication { public static void main(String[] args) { - ApplicationContext context = SpringApplication.run(VoucherManagementSystemApplication.class, args); - CommandMainApplication application = context.getBean(CommandMainApplication.class); + Console.print(""" + === 실행할 애플리케이션을 선택해주세요. === + 0. Console Application + 1. Web Application"""); - application.run(); + selectApplication(args); Console.close(); } + + private static void selectApplication(String[] args) { + String input = Console.readString(); + + switch (input) { + case "0" -> ConsoleApplication.main(args); + case "1" -> WebApplication.main(args); + default -> reselect(args); + } + } + + private static void reselect(String[] args) { + Console.print("사용할 수 없는 애플리케이션 입니다."); + + selectApplication(args); + } } diff --git a/src/main/java/team/marco/voucher_management_system/WebApplication.java b/src/main/java/team/marco/voucher_management_system/WebApplication.java new file mode 100644 index 0000000000..5d1df98ae4 --- /dev/null +++ b/src/main/java/team/marco/voucher_management_system/WebApplication.java @@ -0,0 +1,13 @@ +package team.marco.voucher_management_system; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.context.properties.ConfigurationPropertiesScan; + +@SpringBootApplication +@ConfigurationPropertiesScan +public class WebApplication { + public static void main(String[] args) { + SpringApplication.run(WebApplication.class, args); + } +} From 9d2b545f6b0e98858552c03b1becbe6688002fff Mon Sep 17 00:00:00 2001 From: ASak1104 Date: Mon, 6 Nov 2023 11:51:08 +0900 Subject: [PATCH 42/73] =?UTF-8?q?refactor=20:=20=EC=95=A0=ED=94=8C?= =?UTF-8?q?=EB=A6=AC=EC=BC=80=EC=9D=B4=EC=85=98=EB=93=A4=EC=9D=98=20?= =?UTF-8?q?=ED=8C=A8=ED=82=A4=EC=A7=80=EB=A5=BC=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../VoucherManagementSystemApplication.java | 6 ++++++ .../{ => console_app}/ConsoleApplication.java | 7 ++++--- .../{ => web_app}/WebApplication.java | 7 ++++--- 3 files changed, 14 insertions(+), 6 deletions(-) rename src/main/java/team/marco/voucher_management_system/{ => console_app}/ConsoleApplication.java (77%) rename src/main/java/team/marco/voucher_management_system/{ => web_app}/WebApplication.java (54%) diff --git a/src/main/java/team/marco/voucher_management_system/VoucherManagementSystemApplication.java b/src/main/java/team/marco/voucher_management_system/VoucherManagementSystemApplication.java index e3fc83934b..52bde7d441 100644 --- a/src/main/java/team/marco/voucher_management_system/VoucherManagementSystemApplication.java +++ b/src/main/java/team/marco/voucher_management_system/VoucherManagementSystemApplication.java @@ -1,7 +1,13 @@ package team.marco.voucher_management_system; +import org.springframework.boot.context.properties.ConfigurationPropertiesScan; +import org.springframework.context.annotation.ComponentScan; +import team.marco.voucher_management_system.console_app.ConsoleApplication; import team.marco.voucher_management_system.util.Console; +import team.marco.voucher_management_system.web_app.WebApplication; +@ComponentScan +@ConfigurationPropertiesScan public class VoucherManagementSystemApplication { public static void main(String[] args) { Console.print(""" diff --git a/src/main/java/team/marco/voucher_management_system/ConsoleApplication.java b/src/main/java/team/marco/voucher_management_system/console_app/ConsoleApplication.java similarity index 77% rename from src/main/java/team/marco/voucher_management_system/ConsoleApplication.java rename to src/main/java/team/marco/voucher_management_system/console_app/ConsoleApplication.java index 0b00f428cb..aa2eb3c933 100644 --- a/src/main/java/team/marco/voucher_management_system/ConsoleApplication.java +++ b/src/main/java/team/marco/voucher_management_system/console_app/ConsoleApplication.java @@ -1,14 +1,15 @@ -package team.marco.voucher_management_system; +package team.marco.voucher_management_system.console_app; import org.springframework.boot.SpringApplication; import org.springframework.boot.WebApplicationType; import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.boot.context.properties.ConfigurationPropertiesScan; import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.context.annotation.Import; +import team.marco.voucher_management_system.VoucherManagementSystemApplication; import team.marco.voucher_management_system.console_app.application.CommandMainApplication; +@Import(VoucherManagementSystemApplication.class) @SpringBootApplication -@ConfigurationPropertiesScan public class ConsoleApplication { public static void main(String[] args) { SpringApplication springApplication = new SpringApplication(ConsoleApplication.class); diff --git a/src/main/java/team/marco/voucher_management_system/WebApplication.java b/src/main/java/team/marco/voucher_management_system/web_app/WebApplication.java similarity index 54% rename from src/main/java/team/marco/voucher_management_system/WebApplication.java rename to src/main/java/team/marco/voucher_management_system/web_app/WebApplication.java index 5d1df98ae4..aa5fa557e8 100644 --- a/src/main/java/team/marco/voucher_management_system/WebApplication.java +++ b/src/main/java/team/marco/voucher_management_system/web_app/WebApplication.java @@ -1,11 +1,12 @@ -package team.marco.voucher_management_system; +package team.marco.voucher_management_system.web_app; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.boot.context.properties.ConfigurationPropertiesScan; +import org.springframework.context.annotation.Import; +import team.marco.voucher_management_system.VoucherManagementSystemApplication; +@Import(VoucherManagementSystemApplication.class) @SpringBootApplication -@ConfigurationPropertiesScan public class WebApplication { public static void main(String[] args) { SpringApplication.run(WebApplication.class, args); From 3a7976b221dd3e93432d291edab83a27b94584e8 Mon Sep 17 00:00:00 2001 From: ASak1104 Date: Mon, 6 Nov 2023 11:59:09 +0900 Subject: [PATCH 43/73] =?UTF-8?q?refactor=20:=20=ED=8C=A8=ED=82=A4?= =?UTF-8?q?=EC=A7=80=20=EA=B5=AC=EC=A1=B0=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../console_app/application/CommandCustomerApplication.java | 2 +- .../console_app/application/CommandMainApplication.java | 2 +- .../console_app/application/CommandWalletApplication.java | 2 +- .../command_enum}/CustomerCommandType.java | 2 +- .../command_enum}/MainCommandType.java | 2 +- .../command_enum}/WalletCommandType.java | 2 +- .../{ => console_app}/properties/FilePathProperties.java | 2 +- .../{ => console_app}/repository/BlacklistRepository.java | 4 ++-- .../repository/JSONFileVoucherRepository.java | 5 +++-- .../repository/MemoryVoucherRepository.java | 3 ++- .../voucher_management_system/service/BlacklistService.java | 2 +- .../configuration/TestPropertyConfiguration.java | 2 +- .../properties/FilePathPropertiesTest.java | 1 + .../repository/BlacklistRepositoryTest.java | 3 ++- .../repository/JSONFileVoucherRepositoryTest.java | 3 ++- .../repository/MemoryVoucherRepositoryTest.java | 2 ++ 16 files changed, 23 insertions(+), 16 deletions(-) rename src/main/java/team/marco/voucher_management_system/{type_enum => console_app/command_enum}/CustomerCommandType.java (86%) rename src/main/java/team/marco/voucher_management_system/{type_enum => console_app/command_enum}/MainCommandType.java (86%) rename src/main/java/team/marco/voucher_management_system/{type_enum => console_app/command_enum}/WalletCommandType.java (85%) rename src/main/java/team/marco/voucher_management_system/{ => console_app}/properties/FilePathProperties.java (75%) rename src/main/java/team/marco/voucher_management_system/{ => console_app}/repository/BlacklistRepository.java (89%) rename src/main/java/team/marco/voucher_management_system/{ => console_app}/repository/JSONFileVoucherRepository.java (93%) rename src/main/java/team/marco/voucher_management_system/{ => console_app}/repository/MemoryVoucherRepository.java (92%) diff --git a/src/main/java/team/marco/voucher_management_system/console_app/application/CommandCustomerApplication.java b/src/main/java/team/marco/voucher_management_system/console_app/application/CommandCustomerApplication.java index a8ba056e85..c67fbf0906 100644 --- a/src/main/java/team/marco/voucher_management_system/console_app/application/CommandCustomerApplication.java +++ b/src/main/java/team/marco/voucher_management_system/console_app/application/CommandCustomerApplication.java @@ -6,8 +6,8 @@ import org.springframework.dao.DuplicateKeyException; import org.springframework.jdbc.datasource.lookup.DataSourceLookupFailureException; import org.springframework.stereotype.Component; +import team.marco.voucher_management_system.console_app.command_enum.CustomerCommandType; import team.marco.voucher_management_system.console_app.controller.ConsoleCustomerController; -import team.marco.voucher_management_system.type_enum.CustomerCommandType; import team.marco.voucher_management_system.util.Console; @Component diff --git a/src/main/java/team/marco/voucher_management_system/console_app/application/CommandMainApplication.java b/src/main/java/team/marco/voucher_management_system/console_app/application/CommandMainApplication.java index 09e0736de7..e9d4d9f70d 100644 --- a/src/main/java/team/marco/voucher_management_system/console_app/application/CommandMainApplication.java +++ b/src/main/java/team/marco/voucher_management_system/console_app/application/CommandMainApplication.java @@ -4,9 +4,9 @@ import org.slf4j.LoggerFactory; import org.springframework.jdbc.CannotGetJdbcConnectionException; import org.springframework.stereotype.Component; +import team.marco.voucher_management_system.console_app.command_enum.MainCommandType; import team.marco.voucher_management_system.console_app.controller.ConsoleBlacklistController; import team.marco.voucher_management_system.console_app.controller.ConsoleVoucherController; -import team.marco.voucher_management_system.type_enum.MainCommandType; import team.marco.voucher_management_system.util.Console; @Component diff --git a/src/main/java/team/marco/voucher_management_system/console_app/application/CommandWalletApplication.java b/src/main/java/team/marco/voucher_management_system/console_app/application/CommandWalletApplication.java index ad6b61aa14..bc496876bd 100644 --- a/src/main/java/team/marco/voucher_management_system/console_app/application/CommandWalletApplication.java +++ b/src/main/java/team/marco/voucher_management_system/console_app/application/CommandWalletApplication.java @@ -5,8 +5,8 @@ import org.slf4j.LoggerFactory; import org.springframework.dao.DuplicateKeyException; import org.springframework.stereotype.Component; +import team.marco.voucher_management_system.console_app.command_enum.WalletCommandType; import team.marco.voucher_management_system.console_app.controller.ConsoleWalletController; -import team.marco.voucher_management_system.type_enum.WalletCommandType; import team.marco.voucher_management_system.util.Console; @Component diff --git a/src/main/java/team/marco/voucher_management_system/type_enum/CustomerCommandType.java b/src/main/java/team/marco/voucher_management_system/console_app/command_enum/CustomerCommandType.java similarity index 86% rename from src/main/java/team/marco/voucher_management_system/type_enum/CustomerCommandType.java rename to src/main/java/team/marco/voucher_management_system/console_app/command_enum/CustomerCommandType.java index 502e56a720..fe83a27194 100644 --- a/src/main/java/team/marco/voucher_management_system/type_enum/CustomerCommandType.java +++ b/src/main/java/team/marco/voucher_management_system/console_app/command_enum/CustomerCommandType.java @@ -1,4 +1,4 @@ -package team.marco.voucher_management_system.type_enum; +package team.marco.voucher_management_system.console_app.command_enum; public enum CustomerCommandType { EXIT, CREATE, LIST, UPDATE, FIND_BY_ID, FIND_BY_NAME, FIND_BY_EMAIL; diff --git a/src/main/java/team/marco/voucher_management_system/type_enum/MainCommandType.java b/src/main/java/team/marco/voucher_management_system/console_app/command_enum/MainCommandType.java similarity index 86% rename from src/main/java/team/marco/voucher_management_system/type_enum/MainCommandType.java rename to src/main/java/team/marco/voucher_management_system/console_app/command_enum/MainCommandType.java index 856b82336c..8c6bfae0f5 100644 --- a/src/main/java/team/marco/voucher_management_system/type_enum/MainCommandType.java +++ b/src/main/java/team/marco/voucher_management_system/console_app/command_enum/MainCommandType.java @@ -1,4 +1,4 @@ -package team.marco.voucher_management_system.type_enum; +package team.marco.voucher_management_system.console_app.command_enum; import static java.text.MessageFormat.format; diff --git a/src/main/java/team/marco/voucher_management_system/type_enum/WalletCommandType.java b/src/main/java/team/marco/voucher_management_system/console_app/command_enum/WalletCommandType.java similarity index 85% rename from src/main/java/team/marco/voucher_management_system/type_enum/WalletCommandType.java rename to src/main/java/team/marco/voucher_management_system/console_app/command_enum/WalletCommandType.java index e9301dc999..6222ed66ed 100644 --- a/src/main/java/team/marco/voucher_management_system/type_enum/WalletCommandType.java +++ b/src/main/java/team/marco/voucher_management_system/console_app/command_enum/WalletCommandType.java @@ -1,4 +1,4 @@ -package team.marco.voucher_management_system.type_enum; +package team.marco.voucher_management_system.console_app.command_enum; public enum WalletCommandType { EXIT, SUPPLY, VOUCHER_LIST, RETURN, CUSTOMER_LIST; diff --git a/src/main/java/team/marco/voucher_management_system/properties/FilePathProperties.java b/src/main/java/team/marco/voucher_management_system/console_app/properties/FilePathProperties.java similarity index 75% rename from src/main/java/team/marco/voucher_management_system/properties/FilePathProperties.java rename to src/main/java/team/marco/voucher_management_system/console_app/properties/FilePathProperties.java index b94457dffd..9c88d6a827 100644 --- a/src/main/java/team/marco/voucher_management_system/properties/FilePathProperties.java +++ b/src/main/java/team/marco/voucher_management_system/console_app/properties/FilePathProperties.java @@ -1,4 +1,4 @@ -package team.marco.voucher_management_system.properties; +package team.marco.voucher_management_system.console_app.properties; import org.springframework.boot.context.properties.ConfigurationProperties; diff --git a/src/main/java/team/marco/voucher_management_system/repository/BlacklistRepository.java b/src/main/java/team/marco/voucher_management_system/console_app/repository/BlacklistRepository.java similarity index 89% rename from src/main/java/team/marco/voucher_management_system/repository/BlacklistRepository.java rename to src/main/java/team/marco/voucher_management_system/console_app/repository/BlacklistRepository.java index 66c7997fbe..1d8a0b5ec7 100644 --- a/src/main/java/team/marco/voucher_management_system/repository/BlacklistRepository.java +++ b/src/main/java/team/marco/voucher_management_system/console_app/repository/BlacklistRepository.java @@ -1,4 +1,4 @@ -package team.marco.voucher_management_system.repository; +package team.marco.voucher_management_system.console_app.repository; import java.io.BufferedReader; import java.io.IOException; @@ -10,8 +10,8 @@ import java.util.List; import java.util.UUID; import org.springframework.stereotype.Repository; +import team.marco.voucher_management_system.console_app.properties.FilePathProperties; import team.marco.voucher_management_system.model.BlacklistUser; -import team.marco.voucher_management_system.properties.FilePathProperties; @Repository public class BlacklistRepository { diff --git a/src/main/java/team/marco/voucher_management_system/repository/JSONFileVoucherRepository.java b/src/main/java/team/marco/voucher_management_system/console_app/repository/JSONFileVoucherRepository.java similarity index 93% rename from src/main/java/team/marco/voucher_management_system/repository/JSONFileVoucherRepository.java rename to src/main/java/team/marco/voucher_management_system/console_app/repository/JSONFileVoucherRepository.java index 135b2dfe13..b13b9ec3ca 100644 --- a/src/main/java/team/marco/voucher_management_system/repository/JSONFileVoucherRepository.java +++ b/src/main/java/team/marco/voucher_management_system/console_app/repository/JSONFileVoucherRepository.java @@ -1,4 +1,4 @@ -package team.marco.voucher_management_system.repository; +package team.marco.voucher_management_system.console_app.repository; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectReader; @@ -14,9 +14,10 @@ import org.springframework.beans.factory.DisposableBean; import org.springframework.context.annotation.Profile; import org.springframework.stereotype.Repository; +import team.marco.voucher_management_system.console_app.properties.FilePathProperties; import team.marco.voucher_management_system.model.LoadedVoucher; import team.marco.voucher_management_system.model.Voucher; -import team.marco.voucher_management_system.properties.FilePathProperties; +import team.marco.voucher_management_system.repository.VoucherRepository; import team.marco.voucher_management_system.type_enum.VoucherType; @Profile("dev") diff --git a/src/main/java/team/marco/voucher_management_system/repository/MemoryVoucherRepository.java b/src/main/java/team/marco/voucher_management_system/console_app/repository/MemoryVoucherRepository.java similarity index 92% rename from src/main/java/team/marco/voucher_management_system/repository/MemoryVoucherRepository.java rename to src/main/java/team/marco/voucher_management_system/console_app/repository/MemoryVoucherRepository.java index 7c09c3c3ff..6cea8af33a 100644 --- a/src/main/java/team/marco/voucher_management_system/repository/MemoryVoucherRepository.java +++ b/src/main/java/team/marco/voucher_management_system/console_app/repository/MemoryVoucherRepository.java @@ -1,4 +1,4 @@ -package team.marco.voucher_management_system.repository; +package team.marco.voucher_management_system.console_app.repository; import java.time.LocalDateTime; import java.util.HashMap; @@ -9,6 +9,7 @@ import org.springframework.context.annotation.Profile; import org.springframework.stereotype.Repository; import team.marco.voucher_management_system.model.Voucher; +import team.marco.voucher_management_system.repository.VoucherRepository; import team.marco.voucher_management_system.type_enum.VoucherType; @Profile({"debug", "test"}) diff --git a/src/main/java/team/marco/voucher_management_system/service/BlacklistService.java b/src/main/java/team/marco/voucher_management_system/service/BlacklistService.java index 6609b4069a..3aec6d7319 100644 --- a/src/main/java/team/marco/voucher_management_system/service/BlacklistService.java +++ b/src/main/java/team/marco/voucher_management_system/service/BlacklistService.java @@ -2,8 +2,8 @@ import java.util.List; import org.springframework.stereotype.Service; +import team.marco.voucher_management_system.console_app.repository.BlacklistRepository; import team.marco.voucher_management_system.model.BlacklistUser; -import team.marco.voucher_management_system.repository.BlacklistRepository; @Service public class BlacklistService { diff --git a/src/test/java/team/marco/voucher_management_system/configuration/TestPropertyConfiguration.java b/src/test/java/team/marco/voucher_management_system/configuration/TestPropertyConfiguration.java index af682cb63b..6cb1a282a8 100644 --- a/src/test/java/team/marco/voucher_management_system/configuration/TestPropertyConfiguration.java +++ b/src/test/java/team/marco/voucher_management_system/configuration/TestPropertyConfiguration.java @@ -3,8 +3,8 @@ import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.test.context.TestConfiguration; import org.springframework.context.annotation.PropertySource; +import team.marco.voucher_management_system.console_app.properties.FilePathProperties; import team.marco.voucher_management_system.factory.YamlPropertiesFactory; -import team.marco.voucher_management_system.properties.FilePathProperties; @TestConfiguration @EnableConfigurationProperties({FilePathProperties.class, TestDataSourceProperties.class}) diff --git a/src/test/java/team/marco/voucher_management_system/properties/FilePathPropertiesTest.java b/src/test/java/team/marco/voucher_management_system/properties/FilePathPropertiesTest.java index 8cab3ce9c0..1468b42525 100644 --- a/src/test/java/team/marco/voucher_management_system/properties/FilePathPropertiesTest.java +++ b/src/test/java/team/marco/voucher_management_system/properties/FilePathPropertiesTest.java @@ -10,6 +10,7 @@ import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; import team.marco.voucher_management_system.configuration.TestPropertyConfiguration; +import team.marco.voucher_management_system.console_app.properties.FilePathProperties; @SpringJUnitConfig(classes = TestPropertyConfiguration.class) @EnableConfigurationProperties(FilePathProperties.class) diff --git a/src/test/java/team/marco/voucher_management_system/repository/BlacklistRepositoryTest.java b/src/test/java/team/marco/voucher_management_system/repository/BlacklistRepositoryTest.java index 18c9a167f6..c2e48758bc 100644 --- a/src/test/java/team/marco/voucher_management_system/repository/BlacklistRepositoryTest.java +++ b/src/test/java/team/marco/voucher_management_system/repository/BlacklistRepositoryTest.java @@ -15,8 +15,9 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; import team.marco.voucher_management_system.configuration.TestPropertyConfiguration; +import team.marco.voucher_management_system.console_app.properties.FilePathProperties; +import team.marco.voucher_management_system.console_app.repository.BlacklistRepository; import team.marco.voucher_management_system.model.BlacklistUser; -import team.marco.voucher_management_system.properties.FilePathProperties; @TestInstance(TestInstance.Lifecycle.PER_CLASS) @SpringJUnitConfig(classes = {TestPropertyConfiguration.class, BlacklistRepository.class}) diff --git a/src/test/java/team/marco/voucher_management_system/repository/JSONFileVoucherRepositoryTest.java b/src/test/java/team/marco/voucher_management_system/repository/JSONFileVoucherRepositoryTest.java index 55d0c16ff0..31327447f4 100644 --- a/src/test/java/team/marco/voucher_management_system/repository/JSONFileVoucherRepositoryTest.java +++ b/src/test/java/team/marco/voucher_management_system/repository/JSONFileVoucherRepositoryTest.java @@ -17,8 +17,9 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; import team.marco.voucher_management_system.configuration.TestPropertyConfiguration; +import team.marco.voucher_management_system.console_app.properties.FilePathProperties; +import team.marco.voucher_management_system.console_app.repository.JSONFileVoucherRepository; import team.marco.voucher_management_system.model.Voucher; -import team.marco.voucher_management_system.properties.FilePathProperties; @TestInstance(TestInstance.Lifecycle.PER_CLASS) @SpringJUnitConfig(TestPropertyConfiguration.class) diff --git a/src/test/java/team/marco/voucher_management_system/repository/MemoryVoucherRepositoryTest.java b/src/test/java/team/marco/voucher_management_system/repository/MemoryVoucherRepositoryTest.java index 5d494fee68..afcb84e7b5 100644 --- a/src/test/java/team/marco/voucher_management_system/repository/MemoryVoucherRepositoryTest.java +++ b/src/test/java/team/marco/voucher_management_system/repository/MemoryVoucherRepositoryTest.java @@ -1,5 +1,7 @@ package team.marco.voucher_management_system.repository; +import team.marco.voucher_management_system.console_app.repository.MemoryVoucherRepository; + class MemoryVoucherRepositoryTest extends VoucherRepositoryTest { protected VoucherRepository getRepository() { return new MemoryVoucherRepository(); From 39b416d4bb9c9224f6743ddc748b0de9c7f6a3d4 Mon Sep 17 00:00:00 2001 From: ASak1104 Date: Mon, 6 Nov 2023 18:19:15 +0900 Subject: [PATCH 44/73] =?UTF-8?q?test=20:=20=ED=95=84=EC=9A=94=EC=97=86?= =?UTF-8?q?=EB=8A=94=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EB=B6=80=EB=B6=84=20?= =?UTF-8?q?=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../VoucherManagementSystemApplicationTests.java | 11 ----------- .../voucher_management_system/util/ConsoleTest.java | 2 -- 2 files changed, 13 deletions(-) delete mode 100644 src/test/java/team/marco/voucher_management_system/VoucherManagementSystemApplicationTests.java diff --git a/src/test/java/team/marco/voucher_management_system/VoucherManagementSystemApplicationTests.java b/src/test/java/team/marco/voucher_management_system/VoucherManagementSystemApplicationTests.java deleted file mode 100644 index 3ba77e6edc..0000000000 --- a/src/test/java/team/marco/voucher_management_system/VoucherManagementSystemApplicationTests.java +++ /dev/null @@ -1,11 +0,0 @@ -package team.marco.voucher_management_system; - -import org.junit.jupiter.api.Test; -import org.springframework.boot.test.context.SpringBootTest; - -@SpringBootTest -class VoucherManagementSystemApplicationTests { - @Test - void contextLoads() { - } -} diff --git a/src/test/java/team/marco/voucher_management_system/util/ConsoleTest.java b/src/test/java/team/marco/voucher_management_system/util/ConsoleTest.java index 75df9e2c67..73c1dc7916 100644 --- a/src/test/java/team/marco/voucher_management_system/util/ConsoleTest.java +++ b/src/test/java/team/marco/voucher_management_system/util/ConsoleTest.java @@ -14,9 +14,7 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; -import org.springframework.test.annotation.DirtiesContext; -@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD) class ConsoleTest { private final static Faker faker = new Faker(); private final static String EOF = "\u001a"; From dbeddfa6519c9de017f54a3a9ad74269e956d5fa Mon Sep 17 00:00:00 2001 From: ASak1104 Date: Mon, 6 Nov 2023 18:19:48 +0900 Subject: [PATCH 45/73] =?UTF-8?q?logging=20:=20repository=20pointcut=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../marco/voucher_management_system/aspect/LoggingPointCut.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/team/marco/voucher_management_system/aspect/LoggingPointCut.java b/src/main/java/team/marco/voucher_management_system/aspect/LoggingPointCut.java index c4141fb709..ac92b0c4d9 100644 --- a/src/main/java/team/marco/voucher_management_system/aspect/LoggingPointCut.java +++ b/src/main/java/team/marco/voucher_management_system/aspect/LoggingPointCut.java @@ -14,7 +14,7 @@ public static void controllerMethodPointcut() { public static void serviceMethodPointcut() { } - @Pointcut("execution(* team.marco.voucher_management_system.repository..*(..))") + @Pointcut("execution(* team.marco.voucher_management_system..repository..*(..))") public static void repositorySavePointcut() { } } From c9709836fb522c4a9b6d44325f2fcce95899f8fc Mon Sep 17 00:00:00 2001 From: ASak1104 Date: Mon, 6 Nov 2023 19:12:46 +0900 Subject: [PATCH 46/73] =?UTF-8?q?style=20:=20api=20=EA=B3=B5=ED=86=B5=20pa?= =?UTF-8?q?th=20=EC=B6=94=EC=B6=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../web_app/controller/VoucherController.java | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/main/java/team/marco/voucher_management_system/web_app/controller/VoucherController.java b/src/main/java/team/marco/voucher_management_system/web_app/controller/VoucherController.java index a95e8809d8..f975c9258a 100644 --- a/src/main/java/team/marco/voucher_management_system/web_app/controller/VoucherController.java +++ b/src/main/java/team/marco/voucher_management_system/web_app/controller/VoucherController.java @@ -20,7 +20,9 @@ import team.marco.voucher_management_system.web_app.dto.CreateVoucherRequest; @RestController -@RequestMapping(produces = {MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE}) +@RequestMapping( + value = "/api/vouchers", + produces = {MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE}) public class VoucherController { private static final String DATE_PATTERN = "yyyy-MM-dd HH:mm:ss"; @@ -30,19 +32,19 @@ public VoucherController(VoucherService voucherService) { this.voucherService = voucherService; } - @GetMapping("/vouchers") + @GetMapping public List findAll() { return voucherService.getVouchers(); } - @PostMapping("/vouchers") + @PostMapping public ResponseEntity create(CreateVoucherRequest createVoucherRequest) { Voucher voucher = voucherService.create(createVoucherRequest); return ResponseEntity.ok(voucher); } - @GetMapping("/vouchers/{id}") + @GetMapping("/{id}") public ResponseEntity findById(@PathVariable("id") UUID id) { Optional optionalVoucher = voucherService.findById(id); @@ -51,7 +53,7 @@ public ResponseEntity findById(@PathVariable("id") UUID id) { .build()); } - @DeleteMapping("/vouchers/{id}") + @DeleteMapping("/{id}") public ResponseEntity delete(@PathVariable("id") UUID id) { boolean isDeleted = voucherService.deleteById(id); @@ -64,7 +66,7 @@ public ResponseEntity delete(@PathVariable("id") UUID id) { .build(); } - @GetMapping("/vouchers/createdAt") + @GetMapping("/createdAt") public List findByCreateAt(@RequestParam("from") @DateTimeFormat(pattern = DATE_PATTERN) LocalDateTime from, @@ -74,7 +76,7 @@ public List findByCreateAt(@RequestParam("from") return voucherService.findByCreateAt(from, to); } - @GetMapping("/vouchers/type/{type}") + @GetMapping("/type/{type}") public List findByType(@PathVariable("type") VoucherType voucherType) { return voucherService.findByType(voucherType); } From 15215a6a097f87bd8352241b1a174b56ae2c3879 Mon Sep 17 00:00:00 2001 From: ASak1104 Date: Mon, 6 Nov 2023 19:15:21 +0900 Subject: [PATCH 47/73] =?UTF-8?q?chore=20:=20thymeleaf=20=EC=9D=98?= =?UTF-8?q?=EC=A1=B4=EC=84=B1=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 1 + 1 file changed, 1 insertion(+) diff --git a/build.gradle b/build.gradle index b7e292c343..0913bfa42d 100644 --- a/build.gradle +++ b/build.gradle @@ -21,6 +21,7 @@ dependencies { implementation 'org.springframework.boot:spring-boot-starter-aop' implementation 'org.springframework.boot:spring-boot-starter-web' implementation 'org.springframework.boot:spring-boot-starter-jdbc' + implementation 'org.springframework.boot:spring-boot-starter-thymeleaf' implementation 'com.fasterxml.jackson.core:jackson-databind:2.15.2' implementation 'com.fasterxml.jackson.dataformat:jackson-dataformat-xml:2.15.2' implementation 'com.mysql:mysql-connector-j:8.1.0' From db5c341b09cf35d0ad21fe28842eed193e95d3ab Mon Sep 17 00:00:00 2001 From: ASak1104 Date: Mon, 6 Nov 2023 19:15:59 +0900 Subject: [PATCH 48/73] =?UTF-8?q?feat=20:=20=EA=B0=84=EB=8B=A8=ED=95=9C=20?= =?UTF-8?q?=EA=B3=A0=EA=B0=9D=20=ED=8E=98=EC=9D=B4=EC=A7=80=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/CustomerController.java | 19 +++++++++++++++++++ src/main/resources/application.yml | 3 +++ src/main/webapp/WEB-INF/views/customers.html | 10 ++++++++++ 3 files changed, 32 insertions(+) create mode 100644 src/main/java/team/marco/voucher_management_system/web_app/controller/CustomerController.java create mode 100644 src/main/webapp/WEB-INF/views/customers.html diff --git a/src/main/java/team/marco/voucher_management_system/web_app/controller/CustomerController.java b/src/main/java/team/marco/voucher_management_system/web_app/controller/CustomerController.java new file mode 100644 index 0000000000..145418651d --- /dev/null +++ b/src/main/java/team/marco/voucher_management_system/web_app/controller/CustomerController.java @@ -0,0 +1,19 @@ +package team.marco.voucher_management_system.web_app.controller; + +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.GetMapping; +import team.marco.voucher_management_system.service.CustomerService; + +@Controller +public class CustomerController { + private final CustomerService customerService; + + public CustomerController(CustomerService customerService) { + this.customerService = customerService; + } + + @GetMapping("/customers") + public String viewCustomersPage() { + return "views/customers"; + } +} diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 5777c5645b..4f66ba6b9b 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -8,6 +8,9 @@ spring: url: jdbc:mysql://localhost:3306/voucher_management_system username: root password: + thymeleaf: + view-names: views/* + prefix: /WEB-INF/ server: port: 8080 diff --git a/src/main/webapp/WEB-INF/views/customers.html b/src/main/webapp/WEB-INF/views/customers.html new file mode 100644 index 0000000000..d001aaaa74 --- /dev/null +++ b/src/main/webapp/WEB-INF/views/customers.html @@ -0,0 +1,10 @@ + + + + + Hello HTML + + +hihi~~~ + + From 028286d9c29a964c765d07a928a96d32fc82174e Mon Sep 17 00:00:00 2001 From: ASak1104 Date: Tue, 7 Nov 2023 09:55:13 +0900 Subject: [PATCH 49/73] =?UTF-8?q?refactor=20:=20Voucher=20createAt?= =?UTF-8?q?=EC=9D=84=20=EB=B6=88=EB=B3=80=EC=9C=BC=EB=A1=9C=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../model/FixedAmountVoucher.java | 3 +-- .../model/LoadedVoucher.java | 3 +-- .../model/PercentDiscountVoucher.java | 3 +-- .../voucher_management_system/model/Voucher.java | 6 +++--- src/main/webapp/WEB-INF/views/customers.html | 14 +++++++++++--- 5 files changed, 17 insertions(+), 12 deletions(-) diff --git a/src/main/java/team/marco/voucher_management_system/model/FixedAmountVoucher.java b/src/main/java/team/marco/voucher_management_system/model/FixedAmountVoucher.java index ed66e6f71f..00ca60f780 100644 --- a/src/main/java/team/marco/voucher_management_system/model/FixedAmountVoucher.java +++ b/src/main/java/team/marco/voucher_management_system/model/FixedAmountVoucher.java @@ -20,10 +20,9 @@ public FixedAmountVoucher(int amount) { } public FixedAmountVoucher(UUID id, int amount, LocalDateTime createAt) { - super(id); + super(id, createAt); this.amount = amount; - this.createAt = createAt; } private static void validate(int amount) { diff --git a/src/main/java/team/marco/voucher_management_system/model/LoadedVoucher.java b/src/main/java/team/marco/voucher_management_system/model/LoadedVoucher.java index fc02120e11..468e7a8103 100644 --- a/src/main/java/team/marco/voucher_management_system/model/LoadedVoucher.java +++ b/src/main/java/team/marco/voucher_management_system/model/LoadedVoucher.java @@ -13,11 +13,10 @@ private LoadedVoucher() { } public LoadedVoucher(UUID id, VoucherType type, int data, LocalDateTime createAt) { - super(id); + super(id, createAt); this.type = type; this.data = data; - this.createAt = createAt; } @Override diff --git a/src/main/java/team/marco/voucher_management_system/model/PercentDiscountVoucher.java b/src/main/java/team/marco/voucher_management_system/model/PercentDiscountVoucher.java index 0af8b1378d..bcb7d066c7 100644 --- a/src/main/java/team/marco/voucher_management_system/model/PercentDiscountVoucher.java +++ b/src/main/java/team/marco/voucher_management_system/model/PercentDiscountVoucher.java @@ -20,10 +20,9 @@ public PercentDiscountVoucher(int percent) { } public PercentDiscountVoucher(UUID id, int percent, LocalDateTime createAt) { - super(id); + super(id, createAt); this.percent = percent; - this.createAt = createAt; } private void validate(int percent) { diff --git a/src/main/java/team/marco/voucher_management_system/model/Voucher.java b/src/main/java/team/marco/voucher_management_system/model/Voucher.java index eae392ac2f..a005774364 100644 --- a/src/main/java/team/marco/voucher_management_system/model/Voucher.java +++ b/src/main/java/team/marco/voucher_management_system/model/Voucher.java @@ -13,16 +13,16 @@ public abstract class Voucher { protected final UUID id; @JsonSerialize(using = LocalDateTimeSerializer.class) @JsonDeserialize(using = LocalDateTimeDeserializer.class) - protected LocalDateTime createAt; + protected final LocalDateTime createAt; protected Voucher() { this.id = UUID.randomUUID(); this.createAt = LocalDateTime.now(); } - protected Voucher(UUID id) { + protected Voucher(UUID id, LocalDateTime createAt) { this.id = id; - this.createAt = LocalDateTime.now(); + this.createAt = createAt; } public boolean isSameId(UUID id) { diff --git a/src/main/webapp/WEB-INF/views/customers.html b/src/main/webapp/WEB-INF/views/customers.html index d001aaaa74..d4f165f112 100644 --- a/src/main/webapp/WEB-INF/views/customers.html +++ b/src/main/webapp/WEB-INF/views/customers.html @@ -1,10 +1,18 @@ - + - Hello HTML + + + Document + -hihi~~~ +

Hello, world!

+ From 3b66145b90bbe0d3e3cf7ccb340d7d27c6af05e3 Mon Sep 17 00:00:00 2001 From: ASak1104 Date: Tue, 7 Nov 2023 10:24:55 +0900 Subject: [PATCH 50/73] =?UTF-8?q?view=20:=20=EA=B3=A0=EA=B0=9D=20=EA=B4=80?= =?UTF-8?q?=EB=A6=AC=20html=20=ED=8C=8C=EC=9D=BC=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/webapp/WEB-INF/views/customers.html | 32 +++++++++++++++---- .../webapp/WEB-INF/views/new-customer.html | 25 +++++++++++++++ 2 files changed, 51 insertions(+), 6 deletions(-) create mode 100644 src/main/webapp/WEB-INF/views/new-customer.html diff --git a/src/main/webapp/WEB-INF/views/customers.html b/src/main/webapp/WEB-INF/views/customers.html index d4f165f112..3760a28cd5 100644 --- a/src/main/webapp/WEB-INF/views/customers.html +++ b/src/main/webapp/WEB-INF/views/customers.html @@ -1,18 +1,38 @@ - + - Document + Customers -

Hello, world!

- +

Customers

+ + + + + + + + + + + + + + + + + + + + +
IDNameEmailCreatedAtLastLoginAt
diff --git a/src/main/webapp/WEB-INF/views/new-customer.html b/src/main/webapp/WEB-INF/views/new-customer.html new file mode 100644 index 0000000000..1b1be316f0 --- /dev/null +++ b/src/main/webapp/WEB-INF/views/new-customer.html @@ -0,0 +1,25 @@ + + + + + + + + New Customer + + +

New Customer

+
+
+ + +
+
+ + +
+ +
+ From 3b77085dae00f3e36bc81c823f7170a763f146b3 Mon Sep 17 00:00:00 2001 From: ASak1104 Date: Tue, 7 Nov 2023 10:25:30 +0900 Subject: [PATCH 51/73] =?UTF-8?q?feat=20:=20=EA=B3=A0=EA=B0=9D=20view=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/CustomerController.java | 27 +++++++++++++++++-- .../web_app/dto/CreateCustomerRequest.java | 6 +++++ 2 files changed, 31 insertions(+), 2 deletions(-) create mode 100644 src/main/java/team/marco/voucher_management_system/web_app/dto/CreateCustomerRequest.java diff --git a/src/main/java/team/marco/voucher_management_system/web_app/controller/CustomerController.java b/src/main/java/team/marco/voucher_management_system/web_app/controller/CustomerController.java index 145418651d..9e286788df 100644 --- a/src/main/java/team/marco/voucher_management_system/web_app/controller/CustomerController.java +++ b/src/main/java/team/marco/voucher_management_system/web_app/controller/CustomerController.java @@ -1,10 +1,17 @@ package team.marco.voucher_management_system.web_app.controller; +import java.util.List; import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import team.marco.voucher_management_system.model.Customer; import team.marco.voucher_management_system.service.CustomerService; +import team.marco.voucher_management_system.web_app.dto.CreateCustomerRequest; @Controller +@RequestMapping(path = "/customers") public class CustomerController { private final CustomerService customerService; @@ -12,8 +19,24 @@ public CustomerController(CustomerService customerService) { this.customerService = customerService; } - @GetMapping("/customers") - public String viewCustomersPage() { + @GetMapping + public String viewCustomers(Model model) { + List customers = customerService.getCustomers(); + + model.addAttribute("customers", customers); + return "views/customers"; } + + @GetMapping("/new") + public String viewNewCustomer() { + return "views/new-customer"; + } + + @PostMapping("/new") + public String createCustomer(CreateCustomerRequest createCustomerRequest) { + customerService.create(createCustomerRequest.name(), createCustomerRequest.email()); + + return "redirect:/customers"; + } } diff --git a/src/main/java/team/marco/voucher_management_system/web_app/dto/CreateCustomerRequest.java b/src/main/java/team/marco/voucher_management_system/web_app/dto/CreateCustomerRequest.java new file mode 100644 index 0000000000..19c238b32a --- /dev/null +++ b/src/main/java/team/marco/voucher_management_system/web_app/dto/CreateCustomerRequest.java @@ -0,0 +1,6 @@ +package team.marco.voucher_management_system.web_app.dto; + +public record CreateCustomerRequest( + String name, + String email) { +} From b9305673e5e10887cd52fecd3020e7147bdef938 Mon Sep 17 00:00:00 2001 From: ASak1104 Date: Tue, 7 Nov 2023 10:48:53 +0900 Subject: [PATCH 52/73] =?UTF-8?q?feat=20:=20=EA=B3=A0=EA=B0=9D=20=EA=B4=80?= =?UTF-8?q?=EB=A6=AC=20ControllerAdvice=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../web_app/advice/ViewAdvice.java | 14 + src/main/webapp/WEB-INF/static/404.html | 277 ++++++++++++++++++ 2 files changed, 291 insertions(+) create mode 100644 src/main/java/team/marco/voucher_management_system/web_app/advice/ViewAdvice.java create mode 100644 src/main/webapp/WEB-INF/static/404.html diff --git a/src/main/java/team/marco/voucher_management_system/web_app/advice/ViewAdvice.java b/src/main/java/team/marco/voucher_management_system/web_app/advice/ViewAdvice.java new file mode 100644 index 0000000000..b1288c65b5 --- /dev/null +++ b/src/main/java/team/marco/voucher_management_system/web_app/advice/ViewAdvice.java @@ -0,0 +1,14 @@ +package team.marco.voucher_management_system.web_app.advice; + +import java.util.NoSuchElementException; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.bind.annotation.ExceptionHandler; +import team.marco.voucher_management_system.web_app.controller.CustomerController; + +@ControllerAdvice(basePackageClasses = CustomerController.class) +public class ViewAdvice { + @ExceptionHandler(NoSuchElementException.class) + public String noSuchElementHandler() { + return "static/404"; + } +} diff --git a/src/main/webapp/WEB-INF/static/404.html b/src/main/webapp/WEB-INF/static/404.html new file mode 100644 index 0000000000..bc3805e644 --- /dev/null +++ b/src/main/webapp/WEB-INF/static/404.html @@ -0,0 +1,277 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 404 Page not found + + + + From d5efde3342898c06bccbb03a2ed43e301130424c Mon Sep 17 00:00:00 2001 From: ASak1104 Date: Tue, 7 Nov 2023 18:23:04 +0900 Subject: [PATCH 53/73] =?UTF-8?q?feat=20:=20=EA=B3=A0=EA=B0=9D=20=EC=88=98?= =?UTF-8?q?=EC=A0=95=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/CustomerController.java | 19 ++++++++++++ src/main/resources/application.yml | 8 ++++- .../webapp/WEB-INF/views/customer-detail.html | 30 +++++++++++++++++++ 3 files changed, 56 insertions(+), 1 deletion(-) create mode 100644 src/main/webapp/WEB-INF/views/customer-detail.html diff --git a/src/main/java/team/marco/voucher_management_system/web_app/controller/CustomerController.java b/src/main/java/team/marco/voucher_management_system/web_app/controller/CustomerController.java index 9e286788df..a4d57349d8 100644 --- a/src/main/java/team/marco/voucher_management_system/web_app/controller/CustomerController.java +++ b/src/main/java/team/marco/voucher_management_system/web_app/controller/CustomerController.java @@ -1,10 +1,13 @@ package team.marco.voucher_management_system.web_app.controller; import java.util.List; +import java.util.UUID; 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 org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.RequestMapping; import team.marco.voucher_management_system.model.Customer; import team.marco.voucher_management_system.service.CustomerService; @@ -39,4 +42,20 @@ public String createCustomer(CreateCustomerRequest createCustomerRequest) { return "redirect:/customers"; } + + @GetMapping("/{id}") + public String viewCustomerById(@PathVariable("id") UUID id, Model model) { + Customer customer = customerService.findById(id); + + model.addAttribute("customer", customer); + + return "views/customer-detail"; + } + + @PutMapping("/{id}") + public String changeCustomerName(@PathVariable("id") UUID id, String name) { + customerService.update(id, name); + + return "redirect:/customers"; + } } diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 4f66ba6b9b..3413ed4ba2 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -9,8 +9,14 @@ spring: username: root password: thymeleaf: - view-names: views/* + view-names: + - views/* + - static/* prefix: /WEB-INF/ + mvc: + hidden-method: + filter: + enabled: true server: port: 8080 diff --git a/src/main/webapp/WEB-INF/views/customer-detail.html b/src/main/webapp/WEB-INF/views/customer-detail.html new file mode 100644 index 0000000000..2045f403f8 --- /dev/null +++ b/src/main/webapp/WEB-INF/views/customer-detail.html @@ -0,0 +1,30 @@ + + + + + + + + Customer Detail + + +

Customer Detail

+
+
+ + +
+
+ + +
+
+ + +
+ +
+ From 6ec6b673ccef793d505446eba828de82b8237cff Mon Sep 17 00:00:00 2001 From: ASak1104 Date: Tue, 7 Nov 2023 19:21:05 +0900 Subject: [PATCH 54/73] =?UTF-8?q?view=20:=20=EB=B7=B0=20=ED=8C=8C=EC=9D=BC?= =?UTF-8?q?=20=EC=9C=84=EC=B9=98=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../web_app/advice/ViewAdvice.java | 2 +- src/main/resources/application.yml | 5 +++-- .../WEB-INF/static => resources/templates/error}/404.html | 0 .../templates}/views/customer-detail.html | 0 .../WEB-INF => resources/templates}/views/customers.html | 0 .../templates}/views/new-customer.html | 8 ++++---- 6 files changed, 8 insertions(+), 7 deletions(-) rename src/main/{webapp/WEB-INF/static => resources/templates/error}/404.html (100%) rename src/main/{webapp/WEB-INF => resources/templates}/views/customer-detail.html (100%) rename src/main/{webapp/WEB-INF => resources/templates}/views/customers.html (100%) rename src/main/{webapp/WEB-INF => resources/templates}/views/new-customer.html (80%) diff --git a/src/main/java/team/marco/voucher_management_system/web_app/advice/ViewAdvice.java b/src/main/java/team/marco/voucher_management_system/web_app/advice/ViewAdvice.java index b1288c65b5..0b49a18ddc 100644 --- a/src/main/java/team/marco/voucher_management_system/web_app/advice/ViewAdvice.java +++ b/src/main/java/team/marco/voucher_management_system/web_app/advice/ViewAdvice.java @@ -9,6 +9,6 @@ public class ViewAdvice { @ExceptionHandler(NoSuchElementException.class) public String noSuchElementHandler() { - return "static/404"; + return "error/404"; } } diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 3413ed4ba2..16526fd259 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -9,10 +9,11 @@ spring: username: root password: thymeleaf: + prefix: classpath:templates/ + suffix: .html view-names: - views/* - - static/* - prefix: /WEB-INF/ + - error/* mvc: hidden-method: filter: diff --git a/src/main/webapp/WEB-INF/static/404.html b/src/main/resources/templates/error/404.html similarity index 100% rename from src/main/webapp/WEB-INF/static/404.html rename to src/main/resources/templates/error/404.html diff --git a/src/main/webapp/WEB-INF/views/customer-detail.html b/src/main/resources/templates/views/customer-detail.html similarity index 100% rename from src/main/webapp/WEB-INF/views/customer-detail.html rename to src/main/resources/templates/views/customer-detail.html diff --git a/src/main/webapp/WEB-INF/views/customers.html b/src/main/resources/templates/views/customers.html similarity index 100% rename from src/main/webapp/WEB-INF/views/customers.html rename to src/main/resources/templates/views/customers.html diff --git a/src/main/webapp/WEB-INF/views/new-customer.html b/src/main/resources/templates/views/new-customer.html similarity index 80% rename from src/main/webapp/WEB-INF/views/new-customer.html rename to src/main/resources/templates/views/new-customer.html index 1b1be316f0..2c4bc8f1d2 100644 --- a/src/main/webapp/WEB-INF/views/new-customer.html +++ b/src/main/resources/templates/views/new-customer.html @@ -13,12 +13,12 @@

New Customer

- - + +
- - + +
From 7a1de11e1ad5c5a19e2897e6c45fa15489c1b3bb Mon Sep 17 00:00:00 2001 From: ASak1104 Date: Tue, 7 Nov 2023 19:21:40 +0900 Subject: [PATCH 55/73] =?UTF-8?q?view=20:=20=EC=97=90=EB=9F=AC=20=ED=8E=98?= =?UTF-8?q?=EC=9D=B4=EC=A7=80=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/VoucherErrorController.java | 46 +++++++++++++++++++ src/main/resources/templates/error/error.html | 17 +++++++ 2 files changed, 63 insertions(+) create mode 100644 src/main/java/team/marco/voucher_management_system/web_app/controller/VoucherErrorController.java create mode 100644 src/main/resources/templates/error/error.html diff --git a/src/main/java/team/marco/voucher_management_system/web_app/controller/VoucherErrorController.java b/src/main/java/team/marco/voucher_management_system/web_app/controller/VoucherErrorController.java new file mode 100644 index 0000000000..2f6fa53bff --- /dev/null +++ b/src/main/java/team/marco/voucher_management_system/web_app/controller/VoucherErrorController.java @@ -0,0 +1,46 @@ +package team.marco.voucher_management_system.web_app.controller; + +import jakarta.servlet.RequestDispatcher; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import java.text.MessageFormat; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.List; +import org.springframework.boot.web.servlet.error.ErrorController; +import org.springframework.http.HttpStatus; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.GetMapping; + +@Controller +public class VoucherErrorController implements ErrorController { + @GetMapping("/error") + public String handleError(HttpServletRequest request, HttpServletResponse response, Model model) { + Object status = request.getAttribute(RequestDispatcher.ERROR_STATUS_CODE); + int statusCode = Integer.parseInt(status.toString()); + + response.setStatus(statusCode); + + List header = getHeader(request); + + model.addAttribute("status", status); + model.addAttribute("message", HttpStatus.valueOf(statusCode).getReasonPhrase()); + model.addAttribute("header", header); + + return "error/error"; + } + + private List getHeader(HttpServletRequest request) { + List headerItems = new ArrayList<>(); + Enumeration headerNames = request.getHeaderNames(); + + while (headerNames.hasMoreElements()) { + String headerName = headerNames.nextElement(); + + headerItems.add(MessageFormat.format("{0} : {1}", headerName, request.getHeader(headerName))); + } + + return headerItems; + } +} diff --git a/src/main/resources/templates/error/error.html b/src/main/resources/templates/error/error.html new file mode 100644 index 0000000000..411a0fb5a8 --- /dev/null +++ b/src/main/resources/templates/error/error.html @@ -0,0 +1,17 @@ + + + + + + + +

error page

+
+

status :

+

message :

+
+
+

header

+

+ + From 73686fb6228293929d775090cae6ce86ccfacd98 Mon Sep 17 00:00:00 2001 From: ASak1104 Date: Tue, 7 Nov 2023 20:28:39 +0900 Subject: [PATCH 56/73] =?UTF-8?q?feat=20:=20=EA=B3=A0=EA=B0=9D=20=EC=82=AD?= =?UTF-8?q?=EC=A0=9C=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../repository/CustomerRepository.java | 2 ++ .../repository/JdbcCustomerRepository.java | 15 +++++++++------ .../service/CustomerService.java | 10 +++++++++- .../web_app/controller/CustomerController.java | 8 ++++++++ 4 files changed, 28 insertions(+), 7 deletions(-) diff --git a/src/main/java/team/marco/voucher_management_system/repository/CustomerRepository.java b/src/main/java/team/marco/voucher_management_system/repository/CustomerRepository.java index e361dee002..25a8824f79 100644 --- a/src/main/java/team/marco/voucher_management_system/repository/CustomerRepository.java +++ b/src/main/java/team/marco/voucher_management_system/repository/CustomerRepository.java @@ -17,4 +17,6 @@ public interface CustomerRepository { List findByName(String name); List findByEmail(String email); + + int deleteById(UUID id); } diff --git a/src/main/java/team/marco/voucher_management_system/repository/JdbcCustomerRepository.java b/src/main/java/team/marco/voucher_management_system/repository/JdbcCustomerRepository.java index 1e8b25a152..d403088685 100644 --- a/src/main/java/team/marco/voucher_management_system/repository/JdbcCustomerRepository.java +++ b/src/main/java/team/marco/voucher_management_system/repository/JdbcCustomerRepository.java @@ -70,8 +70,7 @@ public int update(Customer customer) { public Optional findById(UUID id) { try { Customer customer = jdbcTemplate.queryForObject( - "SELECT * FROM customer" - + " WHERE id = UUID_TO_BIN(:id)", + "SELECT * FROM customer WHERE id = UUID_TO_BIN(:id)", Collections.singletonMap("id", id.toString().getBytes()), customerRowMapper); @@ -84,8 +83,7 @@ public Optional findById(UUID id) { @Override public List findByName(String name) { return jdbcTemplate.query( - "SELECT * FROM customer" - + " WHERE name LIKE :name", + "SELECT * FROM customer WHERE name LIKE :name", Collections.singletonMap("name", withWildCards(name)), customerRowMapper); } @@ -93,12 +91,17 @@ public List findByName(String name) { @Override public List findByEmail(String email) { return jdbcTemplate.query( - "SELECT * FROM customer" - + " WHERE email LIKE :email", + "SELECT * FROM customer WHERE email LIKE :email", Collections.singletonMap("email", withWildCards(email)), customerRowMapper); } + @Override + public int deleteById(UUID id) { + return jdbcTemplate.update("DELETE FROM customer WHERE id = UUID_TO_BIN(:id)", + Collections.singletonMap("id", id.toString().getBytes())); + } + private Map customerToMap(Customer customer) { Map customerFields = getCustomerFields(customer); diff --git a/src/main/java/team/marco/voucher_management_system/service/CustomerService.java b/src/main/java/team/marco/voucher_management_system/service/CustomerService.java index 38759fe7ff..38a0a5f312 100644 --- a/src/main/java/team/marco/voucher_management_system/service/CustomerService.java +++ b/src/main/java/team/marco/voucher_management_system/service/CustomerService.java @@ -40,7 +40,7 @@ public void update(UUID id, String name) { int update = customerRepository.update(customer); if (update != 1) { - throw new DataSourceLookupFailureException("고객을 추가하는 과정에서 오류가 발생했습니다."); + throw new DataSourceLookupFailureException("이름을 변경하는 과정에서 오류가 발생했습니다."); } } @@ -50,6 +50,14 @@ public Customer findById(UUID id) { return customerOptional.orElseThrow(); } + public void deleteById(UUID id) { + int delete = customerRepository.deleteById(id); + + if (delete != 1) { + throw new DataSourceLookupFailureException("고객을 삭제하는 과정에서 오류가 발생했습니다."); + } + } + public List findByName(String name) { return customerRepository.findByName(name); } diff --git a/src/main/java/team/marco/voucher_management_system/web_app/controller/CustomerController.java b/src/main/java/team/marco/voucher_management_system/web_app/controller/CustomerController.java index a4d57349d8..8dfa66e72f 100644 --- a/src/main/java/team/marco/voucher_management_system/web_app/controller/CustomerController.java +++ b/src/main/java/team/marco/voucher_management_system/web_app/controller/CustomerController.java @@ -4,6 +4,7 @@ import java.util.UUID; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; @@ -58,4 +59,11 @@ public String changeCustomerName(@PathVariable("id") UUID id, String name) { return "redirect:/customers"; } + + @DeleteMapping("/{id}") + public String deleteCustomerById(@PathVariable("id") UUID id) { + customerService.deleteById(id); + + return "redirect:/customers"; + } } From 894720c8867e42c2ac693ca2b5bdd57e825534c6 Mon Sep 17 00:00:00 2001 From: ASak1104 Date: Tue, 7 Nov 2023 20:28:55 +0900 Subject: [PATCH 57/73] =?UTF-8?q?test=20=20:=20=EA=B3=A0=EA=B0=9D=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=BD=94=EB=93=9C=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../JdbcCustomerRepositoryTest.java | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/src/test/java/team/marco/voucher_management_system/repository/JdbcCustomerRepositoryTest.java b/src/test/java/team/marco/voucher_management_system/repository/JdbcCustomerRepositoryTest.java index d31ecfbee3..698a3cf0c2 100644 --- a/src/test/java/team/marco/voucher_management_system/repository/JdbcCustomerRepositoryTest.java +++ b/src/test/java/team/marco/voucher_management_system/repository/JdbcCustomerRepositoryTest.java @@ -162,6 +162,41 @@ private boolean isContain(String target, String match) { return target.toLowerCase().contains(match.toLowerCase()); } + @Nested + @DisplayName("고객 삭제 테스트") + class TestDeleteById { + @Test + @DisplayName("id가 일치하는 고객이 존재할 경우 삭제할 수 있어야 한다.") + void success() { + // given + Customer existCustomer = generateCustomer(); + + addTestCustomers(10); + repository.create(existCustomer); + + // when + int delete = repository.deleteById(existCustomer.getId()); + + // then + assertThat(delete).isEqualTo(1); + } + + @Test + @DisplayName("id가 일치하는 고객이 없을 경우 0을 반환한다.") + void failToNotExistId() { + // given + Customer notExistCustomer = generateCustomer(); + + addTestCustomers(10); + + // when + int delete = repository.deleteById(notExistCustomer.getId()); + + // then + assertThat(delete).isEqualTo(0); + } + } + @Nested @DisplayName("고객 추가 테스트") class TestCreate { From 750e94442851409d032c4b5cf231dce7bf58428c Mon Sep 17 00:00:00 2001 From: ASak1104 Date: Tue, 7 Nov 2023 20:29:06 +0900 Subject: [PATCH 58/73] =?UTF-8?q?view=20:=20=EA=B3=A0=EA=B0=9D=20=EC=82=AD?= =?UTF-8?q?=EC=A0=9C=20=EB=B2=84=ED=8A=BC=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/resources/templates/views/customer-detail.html | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/resources/templates/views/customer-detail.html b/src/main/resources/templates/views/customer-detail.html index 2045f403f8..75c1679969 100644 --- a/src/main/resources/templates/views/customer-detail.html +++ b/src/main/resources/templates/views/customer-detail.html @@ -11,7 +11,7 @@

Customer Detail

-
+
@@ -25,6 +25,8 @@

Customer Detail

-
+
+ + From 7215e1687ef26bbbd4b7fa0358ca617337cf2ad3 Mon Sep 17 00:00:00 2001 From: ASak1104 Date: Tue, 7 Nov 2023 20:35:01 +0900 Subject: [PATCH 59/73] =?UTF-8?q?view=20:=20=EC=83=81=EC=84=B8=20=ED=8E=98?= =?UTF-8?q?=EC=9D=B4=EC=A7=80=EB=A1=9C=20=EA=B0=80=EB=8A=94=20=EB=A7=81?= =?UTF-8?q?=ED=81=AC=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/resources/templates/views/customers.html | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/main/resources/templates/views/customers.html b/src/main/resources/templates/views/customers.html index 3760a28cd5..1c2255176d 100644 --- a/src/main/resources/templates/views/customers.html +++ b/src/main/resources/templates/views/customers.html @@ -26,7 +26,11 @@

Customers

- + + +
+
+ From 9a01773940ab537d6a61359b94adaf9e287db369 Mon Sep 17 00:00:00 2001 From: ASak1104 Date: Tue, 7 Nov 2023 22:37:43 +0900 Subject: [PATCH 60/73] =?UTF-8?q?test=20:=20=EC=BD=98=EC=86=94=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=EA=B8=B0=EB=8A=A5=EC=9D=84=20=EC=B6=94?= =?UTF-8?q?=EC=83=81=20=ED=81=B4=EB=9E=98=EC=8A=A4=EB=A1=9C=20=EB=B6=84?= =?UTF-8?q?=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/StdIOTest.java | 29 +++++++++++++++++++ .../util/ConsoleTest.java | 24 ++------------- 2 files changed, 32 insertions(+), 21 deletions(-) create mode 100644 src/test/java/team/marco/voucher_management_system/common/StdIOTest.java diff --git a/src/test/java/team/marco/voucher_management_system/common/StdIOTest.java b/src/test/java/team/marco/voucher_management_system/common/StdIOTest.java new file mode 100644 index 0000000000..791ae8ef01 --- /dev/null +++ b/src/test/java/team/marco/voucher_management_system/common/StdIOTest.java @@ -0,0 +1,29 @@ +package team.marco.voucher_management_system.common; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; +import org.junit.jupiter.api.BeforeEach; + +public abstract class StdIOTest { + private final ByteArrayOutputStream outputStreamCaptor = new ByteArrayOutputStream(); + + @BeforeEach + public void setStdout() { + System.setOut(new PrintStream(outputStreamCaptor)); + } + + protected void setStdin(String input) { + System.setIn(new ByteArrayInputStream(input.getBytes())); + } + + protected void setStdin(String delimiter, String... inputs) { + String joinedInput = String.join(delimiter, inputs); + + setStdin(joinedInput); + } + + protected String getStdout() { + return outputStreamCaptor.toString(); + } +} diff --git a/src/test/java/team/marco/voucher_management_system/util/ConsoleTest.java b/src/test/java/team/marco/voucher_management_system/util/ConsoleTest.java index 73c1dc7916..bc32713455 100644 --- a/src/test/java/team/marco/voucher_management_system/util/ConsoleTest.java +++ b/src/test/java/team/marco/voucher_management_system/util/ConsoleTest.java @@ -4,30 +4,20 @@ import static org.assertj.core.api.Assertions.assertThatException; import com.github.javafaker.Faker; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.PrintStream; import java.io.UncheckedIOException; import org.assertj.core.api.ThrowableAssert.ThrowingCallable; import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; +import team.marco.voucher_management_system.common.StdIOTest; -class ConsoleTest { +class ConsoleTest extends StdIOTest { private final static Faker faker = new Faker(); private final static String EOF = "\u001a"; - private final ByteArrayOutputStream outputStreamCaptor = new ByteArrayOutputStream(); - - @BeforeEach - void setup() { - System.setOut(new PrintStream(outputStreamCaptor)); - } - @AfterEach - void cleanup() { + void closeConsole() { Console.close(); } @@ -116,12 +106,4 @@ void testPrint() { assertThat(stdout).startsWith(userOutput); } - - private void setStdin(String input) { - System.setIn(new ByteArrayInputStream(input.getBytes())); - } - - private String getStdout() { - return outputStreamCaptor.toString(); - } } From fc515f7c1528ce4a5a4ae10cc8efabde45041e58 Mon Sep 17 00:00:00 2001 From: ASak1104 Date: Tue, 7 Nov 2023 22:38:09 +0900 Subject: [PATCH 61/73] =?UTF-8?q?test=20:=20=EB=A9=94=EC=9D=B8=20=ED=81=B4?= =?UTF-8?q?=EB=9E=98=EC=8A=A4=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=BD=94?= =?UTF-8?q?=EB=93=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...oucherManagementSystemApplicationTest.java | 121 ++++++++++++++++++ 1 file changed, 121 insertions(+) create mode 100644 src/test/java/team/marco/voucher_management_system/VoucherManagementSystemApplicationTest.java diff --git a/src/test/java/team/marco/voucher_management_system/VoucherManagementSystemApplicationTest.java b/src/test/java/team/marco/voucher_management_system/VoucherManagementSystemApplicationTest.java new file mode 100644 index 0000000000..7213ca04c1 --- /dev/null +++ b/src/test/java/team/marco/voucher_management_system/VoucherManagementSystemApplicationTest.java @@ -0,0 +1,121 @@ +package team.marco.voucher_management_system; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.apache.commons.lang3.ArrayUtils; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import team.marco.voucher_management_system.common.StdIOTest; +import team.marco.voucher_management_system.util.Console; + +class VoucherManagementSystemApplicationTest extends StdIOTest { + private static final String BEAN_OVERRIDING = "--spring.main.allow-bean-definition-overriding=true"; + private static final String ACTIVE_PROD = "--spring.profiles.active=prod"; + private static final String SELECT_APPLICATION_MESSAGE = """ + === 실행할 애플리케이션을 선택해주세요. === + 0. Console Application + 1. Web Application"""; + private static final String UNSUPPORTED_APPLICATION_MESSAGE = "사용할 수 없는 애플리케이션 입니다."; + + private String[] args; + + @BeforeEach + void setup() { + args = new String[0]; + + /* + * To avoid exception + * BeanDefinitionOverrideException : Cause By DataSource from TestJdbcConfiguration.class + * NoUniqueBeanDefinitionException : Cause By memoryVoucherRepository, jdbcVoucherRepository + */ + addProgramArgument(BEAN_OVERRIDING, ACTIVE_PROD); + Console.close(); + } + + @Test + @DisplayName("애플리케이션 선택 화면을 출력한다.") + void testSelectApplication() { + // given + setStdin("0"); + + // when + VoucherManagementSystemApplication.main(args); + + // then + String stdout = getStdout(); + + assertThat(stdout).startsWith(SELECT_APPLICATION_MESSAGE); + } + + @Test + @DisplayName("잘못된 입력일 경우 메시지를 출력한다.") + void testReselectApplication() { + // given + setStdin("\n", "IT CANT BE COMMAND INPUT", "0", "exit"); + + // when + VoucherManagementSystemApplication.main(args); + + // then + String stdout = getStdout(); + + assertThat(stdout).contains(UNSUPPORTED_APPLICATION_MESSAGE); + } + + @Test + @DisplayName("콘솔 애플리케이션을 실행할 수 있다.") + void testRunConsoleApplication() { + // given + setStdin("\n", "0", "exit"); + + // when + VoucherManagementSystemApplication.main(args); + + // then + String stdout = getStdout(); + + assertThat(stdout).contains(""" + === 쿠폰 관리 프로그램 === + exit: 프로그램 종료 + create: 쿠폰 생성 + list: 쿠폰 목록 조회 + blacklist: 블랙 리스트 유저 조회 + customer: 고객 관리 메뉴 + wallet: 지갑 관리 메뉴"""); + } + + @Test + @DisplayName("콘솔 애플리케이션을 종료할 수 있다.") + void testCloseConsoleApplication() { + // given + setStdin("\n", "0", "exit"); + + // when + VoucherManagementSystemApplication.main(args); + + // then + String stdout = getStdout(); + + assertThat(stdout).contains("프로그램이 종료되었습니다."); + } + + @Test + @DisplayName("웹 애플리케이션을 실행할 수 있다.") + void testRunWebApplication() { + // given + setStdin("1"); + + // when + VoucherManagementSystemApplication.main(args); + + // then + String stdout = getStdout(); + + assertThat(stdout).contains("t.m.v.web_app.WebApplication -- Started WebApplication"); + } + + private void addProgramArgument(String... args) { + this.args = ArrayUtils.addAll(this.args, args); + } +} From 948b2a107ede08937b8097872bd8accb49128995 Mon Sep 17 00:00:00 2001 From: ASak1104 Date: Fri, 10 Nov 2023 19:16:03 +0900 Subject: [PATCH 62/73] =?UTF-8?q?refactor=20:=20=EC=BD=98=EC=86=94=20?= =?UTF-8?q?=EC=B4=88=EA=B8=B0=ED=99=94=20=EB=A9=94=EC=84=9C=EB=93=9C?= =?UTF-8?q?=EB=A5=BC=20=EB=B6=88=EB=B3=80=EC=9C=BC=EB=A1=9C=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../team/marco/voucher_management_system/common/StdIOTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/team/marco/voucher_management_system/common/StdIOTest.java b/src/test/java/team/marco/voucher_management_system/common/StdIOTest.java index 791ae8ef01..062c38dcc3 100644 --- a/src/test/java/team/marco/voucher_management_system/common/StdIOTest.java +++ b/src/test/java/team/marco/voucher_management_system/common/StdIOTest.java @@ -9,7 +9,7 @@ public abstract class StdIOTest { private final ByteArrayOutputStream outputStreamCaptor = new ByteArrayOutputStream(); @BeforeEach - public void setStdout() { + final void init() { System.setOut(new PrintStream(outputStreamCaptor)); } From 81d6f1e7137516b2b730421cf925650a553e016b Mon Sep 17 00:00:00 2001 From: ASak1104 Date: Tue, 14 Nov 2023 21:42:05 +0900 Subject: [PATCH 63/73] =?UTF-8?q?style=20:=20=EB=B6=88=ED=95=84=EC=9A=94?= =?UTF-8?q?=ED=95=9C=20=EC=A4=91=EA=B4=84=ED=98=B8=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../repository/JdbcCustomerRepository.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/team/marco/voucher_management_system/repository/JdbcCustomerRepository.java b/src/main/java/team/marco/voucher_management_system/repository/JdbcCustomerRepository.java index d403088685..0669288dc1 100644 --- a/src/main/java/team/marco/voucher_management_system/repository/JdbcCustomerRepository.java +++ b/src/main/java/team/marco/voucher_management_system/repository/JdbcCustomerRepository.java @@ -113,8 +113,7 @@ private Map customerToMap(Customer customer) { } private Map getCustomerFields(Customer customer) { - Map customerFields = new HashMap<>() { - }; + Map customerFields = new HashMap<>(); customerFields.put("id", customer.getId().toString().getBytes()); customerFields.put("name", customer.getName()); From 70a79d98341a4b86df9d932b2060ab2a7836bf40 Mon Sep 17 00:00:00 2001 From: ASak1104 Date: Tue, 14 Nov 2023 22:18:16 +0900 Subject: [PATCH 64/73] =?UTF-8?q?style=20:=20=ED=99=95=EC=8B=A4=ED=95=9C?= =?UTF-8?q?=20=EC=9D=98=EB=AF=B8=EB=A5=BC=20=EB=82=B4=ED=8F=AC=ED=95=98?= =?UTF-8?q?=EB=8F=84=EB=A1=9D=20=EB=A9=94=EC=84=9C=EB=93=9C=20=EB=AA=85?= =?UTF-8?q?=EC=9D=84=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../console_app/controller/ConsoleWalletController.java | 4 ++-- .../voucher_management_system/service/WalletService.java | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/team/marco/voucher_management_system/console_app/controller/ConsoleWalletController.java b/src/main/java/team/marco/voucher_management_system/console_app/controller/ConsoleWalletController.java index d62d6adbfa..9c38e429f4 100644 --- a/src/main/java/team/marco/voucher_management_system/console_app/controller/ConsoleWalletController.java +++ b/src/main/java/team/marco/voucher_management_system/console_app/controller/ConsoleWalletController.java @@ -46,7 +46,7 @@ public void voucherList() { UUID customerId = UUIDConverter.convert(Console.readString()); - List voucherInfos = walletService.findVouchersByCustomerId(customerId) + List voucherInfos = walletService.findReceivedVouchers(customerId) .stream() .map(Voucher::getInfo) .toList(); @@ -81,7 +81,7 @@ public void customerList() { UUID voucherId = UUIDConverter.convert(Console.readString()); walletService.checkVoucherId(voucherId); - List customerInfos = walletService.findCustomersByVoucherId(voucherId) + List customerInfos = walletService.findHavingCustomers(voucherId) .stream() .map(Customer::getInfo) .toList(); diff --git a/src/main/java/team/marco/voucher_management_system/service/WalletService.java b/src/main/java/team/marco/voucher_management_system/service/WalletService.java index de55578502..3a17756f93 100644 --- a/src/main/java/team/marco/voucher_management_system/service/WalletService.java +++ b/src/main/java/team/marco/voucher_management_system/service/WalletService.java @@ -35,7 +35,7 @@ public int supplyVoucher(UUID customerId, UUID voucherId) { return walletRepository.link(customerId, voucherId); } - public List findVouchersByCustomerId(UUID customerId) { + public List findReceivedVouchers(UUID customerId) { List voucherIds = walletRepository.getVoucherIds(customerId); return voucherCustomerFacade.getVouchers(voucherIds); @@ -45,7 +45,7 @@ public int returnVoucher(UUID customerId, UUID voucherId) { return walletRepository.unlink(customerId, voucherId); } - public List findCustomersByVoucherId(UUID voucherId) { + public List findHavingCustomers(UUID voucherId) { List customerIds = walletRepository.getCustomerIds(voucherId); return voucherCustomerFacade.getCustomers(customerIds); From 649f7ffe1dab61ae667b8bbe66818a3757111507 Mon Sep 17 00:00:00 2001 From: ASak1104 Date: Tue, 14 Nov 2023 22:24:53 +0900 Subject: [PATCH 65/73] =?UTF-8?q?style=20:=20=EB=B6=88=ED=95=84=EC=9A=94?= =?UTF-8?q?=ED=95=9C=20param=20=EC=A7=80=EC=A0=95=20=EB=B6=80=EB=B6=84=20?= =?UTF-8?q?=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../web_app/controller/CustomerController.java | 6 +++--- .../web_app/controller/VoucherController.java | 12 ++++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/main/java/team/marco/voucher_management_system/web_app/controller/CustomerController.java b/src/main/java/team/marco/voucher_management_system/web_app/controller/CustomerController.java index 8dfa66e72f..230c3abc5a 100644 --- a/src/main/java/team/marco/voucher_management_system/web_app/controller/CustomerController.java +++ b/src/main/java/team/marco/voucher_management_system/web_app/controller/CustomerController.java @@ -45,7 +45,7 @@ public String createCustomer(CreateCustomerRequest createCustomerRequest) { } @GetMapping("/{id}") - public String viewCustomerById(@PathVariable("id") UUID id, Model model) { + public String viewCustomerById(@PathVariable UUID id, Model model) { Customer customer = customerService.findById(id); model.addAttribute("customer", customer); @@ -54,14 +54,14 @@ public String viewCustomerById(@PathVariable("id") UUID id, Model model) { } @PutMapping("/{id}") - public String changeCustomerName(@PathVariable("id") UUID id, String name) { + public String changeCustomerName(@PathVariable UUID id, String name) { customerService.update(id, name); return "redirect:/customers"; } @DeleteMapping("/{id}") - public String deleteCustomerById(@PathVariable("id") UUID id) { + public String deleteCustomerById(@PathVariable UUID id) { customerService.deleteById(id); return "redirect:/customers"; diff --git a/src/main/java/team/marco/voucher_management_system/web_app/controller/VoucherController.java b/src/main/java/team/marco/voucher_management_system/web_app/controller/VoucherController.java index f975c9258a..1f477d5bb9 100644 --- a/src/main/java/team/marco/voucher_management_system/web_app/controller/VoucherController.java +++ b/src/main/java/team/marco/voucher_management_system/web_app/controller/VoucherController.java @@ -45,7 +45,7 @@ public ResponseEntity create(CreateVoucherRequest createVoucherRequest) } @GetMapping("/{id}") - public ResponseEntity findById(@PathVariable("id") UUID id) { + public ResponseEntity findById(@PathVariable UUID id) { Optional optionalVoucher = voucherService.findById(id); return optionalVoucher.map(ResponseEntity::ok) @@ -54,7 +54,7 @@ public ResponseEntity findById(@PathVariable("id") UUID id) { } @DeleteMapping("/{id}") - public ResponseEntity delete(@PathVariable("id") UUID id) { + public ResponseEntity delete(@PathVariable UUID id) { boolean isDeleted = voucherService.deleteById(id); if (!isDeleted) { @@ -67,17 +67,17 @@ public ResponseEntity delete(@PathVariable("id") UUID id) { } @GetMapping("/createdAt") - public List findByCreateAt(@RequestParam("from") + public List findByCreateAt(@RequestParam @DateTimeFormat(pattern = DATE_PATTERN) LocalDateTime from, - @RequestParam("to") + @RequestParam @DateTimeFormat(pattern = DATE_PATTERN) LocalDateTime to) { return voucherService.findByCreateAt(from, to); } @GetMapping("/type/{type}") - public List findByType(@PathVariable("type") VoucherType voucherType) { - return voucherService.findByType(voucherType); + public List findByType(@PathVariable VoucherType type) { + return voucherService.findByType(type); } } From 1332c72a7ed4b6e051f802d116d902f9496b4a87 Mon Sep 17 00:00:00 2001 From: ASak1104 Date: Tue, 14 Nov 2023 22:52:56 +0900 Subject: [PATCH 66/73] =?UTF-8?q?chore=20:=20spring=20validation=20?= =?UTF-8?q?=EC=9D=98=EC=A1=B4=EC=84=B1=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 1 + 1 file changed, 1 insertion(+) diff --git a/build.gradle b/build.gradle index 0913bfa42d..36db808c04 100644 --- a/build.gradle +++ b/build.gradle @@ -22,6 +22,7 @@ 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' + implementation 'org.springframework.boot:spring-boot-starter-validation' implementation 'com.fasterxml.jackson.core:jackson-databind:2.15.2' implementation 'com.fasterxml.jackson.dataformat:jackson-dataformat-xml:2.15.2' implementation 'com.mysql:mysql-connector-j:8.1.0' From f870b5b641058586b7ed12efc0ce3063161b43a8 Mon Sep 17 00:00:00 2001 From: ASak1104 Date: Tue, 14 Nov 2023 22:53:18 +0900 Subject: [PATCH 67/73] =?UTF-8?q?feat=20:=20=EB=B0=94=EC=9A=B0=EC=B2=98=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=20dto=20=EB=8D=B0=EC=9D=B4=ED=84=B0=20?= =?UTF-8?q?=EA=B2=80=EC=A6=9D=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../web_app/controller/VoucherController.java | 3 ++- .../web_app/dto/CreateVoucherRequest.java | 4 ++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/main/java/team/marco/voucher_management_system/web_app/controller/VoucherController.java b/src/main/java/team/marco/voucher_management_system/web_app/controller/VoucherController.java index 1f477d5bb9..8ecdba53a5 100644 --- a/src/main/java/team/marco/voucher_management_system/web_app/controller/VoucherController.java +++ b/src/main/java/team/marco/voucher_management_system/web_app/controller/VoucherController.java @@ -1,5 +1,6 @@ package team.marco.voucher_management_system.web_app.controller; +import jakarta.validation.Valid; import java.time.LocalDateTime; import java.util.List; import java.util.Optional; @@ -38,7 +39,7 @@ public List findAll() { } @PostMapping - public ResponseEntity create(CreateVoucherRequest createVoucherRequest) { + public ResponseEntity create(@Valid CreateVoucherRequest createVoucherRequest) { Voucher voucher = voucherService.create(createVoucherRequest); return ResponseEntity.ok(voucher); diff --git a/src/main/java/team/marco/voucher_management_system/web_app/dto/CreateVoucherRequest.java b/src/main/java/team/marco/voucher_management_system/web_app/dto/CreateVoucherRequest.java index 5ba23eea1e..afea2813ff 100644 --- a/src/main/java/team/marco/voucher_management_system/web_app/dto/CreateVoucherRequest.java +++ b/src/main/java/team/marco/voucher_management_system/web_app/dto/CreateVoucherRequest.java @@ -1,8 +1,12 @@ package team.marco.voucher_management_system.web_app.dto; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Positive; import team.marco.voucher_management_system.type_enum.VoucherType; public record CreateVoucherRequest( + @NotNull VoucherType type, + @Positive int data) { } From ce79ec0e5fabb4a6eef814f05b36ae5cf2890cda Mon Sep 17 00:00:00 2001 From: ASak1104 Date: Tue, 14 Nov 2023 22:56:19 +0900 Subject: [PATCH 68/73] =?UTF-8?q?feat=20:=20=EA=B3=A0=EA=B0=9D=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=20dto=20=EA=B2=80=EC=A6=9D=20=EA=B8=B0=EB=8A=A5=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../web_app/controller/CustomerController.java | 3 ++- .../web_app/dto/CreateCustomerRequest.java | 5 +++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/main/java/team/marco/voucher_management_system/web_app/controller/CustomerController.java b/src/main/java/team/marco/voucher_management_system/web_app/controller/CustomerController.java index 230c3abc5a..88ca40e75a 100644 --- a/src/main/java/team/marco/voucher_management_system/web_app/controller/CustomerController.java +++ b/src/main/java/team/marco/voucher_management_system/web_app/controller/CustomerController.java @@ -1,5 +1,6 @@ package team.marco.voucher_management_system.web_app.controller; +import jakarta.validation.Valid; import java.util.List; import java.util.UUID; import org.springframework.stereotype.Controller; @@ -38,7 +39,7 @@ public String viewNewCustomer() { } @PostMapping("/new") - public String createCustomer(CreateCustomerRequest createCustomerRequest) { + public String createCustomer(@Valid CreateCustomerRequest createCustomerRequest) { customerService.create(createCustomerRequest.name(), createCustomerRequest.email()); return "redirect:/customers"; diff --git a/src/main/java/team/marco/voucher_management_system/web_app/dto/CreateCustomerRequest.java b/src/main/java/team/marco/voucher_management_system/web_app/dto/CreateCustomerRequest.java index 19c238b32a..3e16e17a09 100644 --- a/src/main/java/team/marco/voucher_management_system/web_app/dto/CreateCustomerRequest.java +++ b/src/main/java/team/marco/voucher_management_system/web_app/dto/CreateCustomerRequest.java @@ -1,6 +1,11 @@ package team.marco.voucher_management_system.web_app.dto; +import jakarta.validation.constraints.Email; +import jakarta.validation.constraints.NotBlank; + public record CreateCustomerRequest( + @NotBlank String name, + @Email String email) { } From f077d7df8e3461cad626c04cb66b77ec4a0b9f92 Mon Sep 17 00:00:00 2001 From: ASak1104 Date: Tue, 14 Nov 2023 23:03:14 +0900 Subject: [PATCH 69/73] =?UTF-8?q?refactor=20:=20=EC=A1=B4=EC=9E=AC?= =?UTF-8?q?=ED=95=98=EC=A7=80=20=EC=95=8A=EB=8A=94=20=EB=B0=94=EC=9A=B0?= =?UTF-8?q?=EC=B2=98=EB=A5=BC=20=EC=82=AD=EC=A0=9C=ED=95=A0=20=EB=95=8C=20?= =?UTF-8?q?=EC=98=88=EC=99=B8=EA=B0=80=20=EB=B0=9C=EC=83=9D=ED=95=98?= =?UTF-8?q?=EB=8F=84=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../voucher_management_system/service/VoucherService.java | 7 +++++-- .../web_app/controller/VoucherController.java | 7 +------ 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/src/main/java/team/marco/voucher_management_system/service/VoucherService.java b/src/main/java/team/marco/voucher_management_system/service/VoucherService.java index 55edc4e59d..fd5396a701 100644 --- a/src/main/java/team/marco/voucher_management_system/service/VoucherService.java +++ b/src/main/java/team/marco/voucher_management_system/service/VoucherService.java @@ -2,6 +2,7 @@ import java.time.LocalDateTime; import java.util.List; +import java.util.NoSuchElementException; import java.util.Optional; import java.util.UUID; import org.springframework.stereotype.Service; @@ -55,10 +56,12 @@ public Voucher create(CreateVoucherRequest createVoucherRequest) { }; } - public boolean deleteById(UUID id) { + public void deleteById(UUID id) { int deleteCount = voucherRepository.deleteById(id); - return deleteCount != 0; + if (deleteCount == 0) { + throw new NoSuchElementException(); + } } public List findByType(VoucherType voucherType) { diff --git a/src/main/java/team/marco/voucher_management_system/web_app/controller/VoucherController.java b/src/main/java/team/marco/voucher_management_system/web_app/controller/VoucherController.java index 8ecdba53a5..18cbd13ed2 100644 --- a/src/main/java/team/marco/voucher_management_system/web_app/controller/VoucherController.java +++ b/src/main/java/team/marco/voucher_management_system/web_app/controller/VoucherController.java @@ -56,12 +56,7 @@ public ResponseEntity findById(@PathVariable UUID id) { @DeleteMapping("/{id}") public ResponseEntity delete(@PathVariable UUID id) { - boolean isDeleted = voucherService.deleteById(id); - - if (!isDeleted) { - return ResponseEntity.noContent() - .build(); - } + voucherService.deleteById(id); return ResponseEntity.ok() .build(); From 51bfeeaf211952dd286c173e933bc8486f18a456 Mon Sep 17 00:00:00 2001 From: ASak1104 Date: Tue, 14 Nov 2023 23:07:31 +0900 Subject: [PATCH 70/73] =?UTF-8?q?refactor=20:=20=EB=B0=94=EC=9A=B0?= =?UTF-8?q?=EC=B2=98=20=EC=83=9D=EC=84=B1=20api=EC=9D=98=20status=20?= =?UTF-8?q?=EC=BD=94=EB=93=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../web_app/controller/VoucherController.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/team/marco/voucher_management_system/web_app/controller/VoucherController.java b/src/main/java/team/marco/voucher_management_system/web_app/controller/VoucherController.java index 18cbd13ed2..cae636e310 100644 --- a/src/main/java/team/marco/voucher_management_system/web_app/controller/VoucherController.java +++ b/src/main/java/team/marco/voucher_management_system/web_app/controller/VoucherController.java @@ -26,6 +26,7 @@ produces = {MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE}) public class VoucherController { private static final String DATE_PATTERN = "yyyy-MM-dd HH:mm:ss"; + private static final int CREATED = 201; private final VoucherService voucherService; @@ -42,7 +43,8 @@ public List findAll() { public ResponseEntity create(@Valid CreateVoucherRequest createVoucherRequest) { Voucher voucher = voucherService.create(createVoucherRequest); - return ResponseEntity.ok(voucher); + return ResponseEntity.status(CREATED) + .body(voucher); } @GetMapping("/{id}") From 7412a89517cdcb9cca240be313f86510f0b8a131 Mon Sep 17 00:00:00 2001 From: ASak1104 Date: Tue, 14 Nov 2023 23:43:54 +0900 Subject: [PATCH 71/73] =?UTF-8?q?refactor=20:=20=EC=8B=A4=ED=96=89?= =?UTF-8?q?=ED=95=A0=20=EC=95=A0=ED=94=8C=EB=A6=AC=EC=BC=80=EC=9D=B4?= =?UTF-8?q?=EC=85=98=EC=9D=84=20=EC=9D=B4=EB=84=98=EC=9C=BC=EB=A1=9C=20?= =?UTF-8?q?=EA=B4=80=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../VoucherManagementSystemApplication.java | 24 ++++++++-------- .../type_enum/ApplicationType.java | 28 +++++++++++++++++++ 2 files changed, 41 insertions(+), 11 deletions(-) create mode 100644 src/main/java/team/marco/voucher_management_system/type_enum/ApplicationType.java diff --git a/src/main/java/team/marco/voucher_management_system/VoucherManagementSystemApplication.java b/src/main/java/team/marco/voucher_management_system/VoucherManagementSystemApplication.java index 52bde7d441..9deeabfedf 100644 --- a/src/main/java/team/marco/voucher_management_system/VoucherManagementSystemApplication.java +++ b/src/main/java/team/marco/voucher_management_system/VoucherManagementSystemApplication.java @@ -1,10 +1,10 @@ package team.marco.voucher_management_system; +import java.util.function.Consumer; import org.springframework.boot.context.properties.ConfigurationPropertiesScan; import org.springframework.context.annotation.ComponentScan; -import team.marco.voucher_management_system.console_app.ConsoleApplication; +import team.marco.voucher_management_system.type_enum.ApplicationType; import team.marco.voucher_management_system.util.Console; -import team.marco.voucher_management_system.web_app.WebApplication; @ComponentScan @ConfigurationPropertiesScan @@ -21,18 +21,20 @@ public static void main(String[] args) { } private static void selectApplication(String[] args) { - String input = Console.readString(); + Consumer mainMethod = getMainMethod(); - switch (input) { - case "0" -> ConsoleApplication.main(args); - case "1" -> WebApplication.main(args); - default -> reselect(args); - } + mainMethod.accept(args); } - private static void reselect(String[] args) { - Console.print("사용할 수 없는 애플리케이션 입니다."); + private static Consumer getMainMethod() { + try { + int input = Console.readInt(); - selectApplication(args); + return ApplicationType.getMainMethod(input); + } catch (IllegalArgumentException e) { + Console.print("사용할 수 없는 애플리케이션 입니다."); + + return getMainMethod(); + } } } diff --git a/src/main/java/team/marco/voucher_management_system/type_enum/ApplicationType.java b/src/main/java/team/marco/voucher_management_system/type_enum/ApplicationType.java new file mode 100644 index 0000000000..aee5610088 --- /dev/null +++ b/src/main/java/team/marco/voucher_management_system/type_enum/ApplicationType.java @@ -0,0 +1,28 @@ +package team.marco.voucher_management_system.type_enum; + +import java.util.function.Consumer; +import team.marco.voucher_management_system.console_app.ConsoleApplication; +import team.marco.voucher_management_system.web_app.WebApplication; + +public enum ApplicationType { + CONSOLE(ConsoleApplication::main), + WEB(WebApplication::main); + + private final Consumer mainMethod; + + ApplicationType(Consumer consumer) { + mainMethod = consumer; + } + + public static Consumer getMainMethod(int index) { + validate(index); + + return values()[index].mainMethod; + } + + private static void validate(int index) { + if (index < 0 || index >= values().length) { + throw new IllegalArgumentException(); + } + } +} From f949bd96bf4f1caaea4488a50f22f22a51c781a8 Mon Sep 17 00:00:00 2001 From: ASak1104 Date: Tue, 14 Nov 2023 23:54:15 +0900 Subject: [PATCH 72/73] =?UTF-8?q?refactor=20:=20=ED=95=84=ED=84=B0?= =?UTF-8?q?=EB=A7=81=20api=EB=A5=BC=20origin=EC=97=90=20=EB=8C=80=ED=95=9C?= =?UTF-8?q?=20=EC=BF=BC=EB=A6=AC=EC=8A=A4=ED=8A=B8=EB=A7=81=EC=9C=BC?= =?UTF-8?q?=EB=A1=9C=20=ED=86=B5=EC=9D=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../web_app/controller/VoucherController.java | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/src/main/java/team/marco/voucher_management_system/web_app/controller/VoucherController.java b/src/main/java/team/marco/voucher_management_system/web_app/controller/VoucherController.java index cae636e310..d9021d94b4 100644 --- a/src/main/java/team/marco/voucher_management_system/web_app/controller/VoucherController.java +++ b/src/main/java/team/marco/voucher_management_system/web_app/controller/VoucherController.java @@ -39,6 +39,21 @@ public List findAll() { return voucherService.getVouchers(); } + @GetMapping(params = {"from", "to"}) + public List findByCreateAt(@RequestParam + @DateTimeFormat(pattern = DATE_PATTERN) + LocalDateTime from, + @RequestParam + @DateTimeFormat(pattern = DATE_PATTERN) + LocalDateTime to) { + return voucherService.findByCreateAt(from, to); + } + + @GetMapping(params = "type") + public List findByType(@RequestParam VoucherType type) { + return voucherService.findByType(type); + } + @PostMapping public ResponseEntity create(@Valid CreateVoucherRequest createVoucherRequest) { Voucher voucher = voucherService.create(createVoucherRequest); @@ -63,19 +78,4 @@ public ResponseEntity delete(@PathVariable UUID id) { return ResponseEntity.ok() .build(); } - - @GetMapping("/createdAt") - public List findByCreateAt(@RequestParam - @DateTimeFormat(pattern = DATE_PATTERN) - LocalDateTime from, - @RequestParam - @DateTimeFormat(pattern = DATE_PATTERN) - LocalDateTime to) { - return voucherService.findByCreateAt(from, to); - } - - @GetMapping("/type/{type}") - public List findByType(@PathVariable VoucherType type) { - return voucherService.findByType(type); - } } From d3c86e4f29e40164af88f4dad2865de5d4d996f9 Mon Sep 17 00:00:00 2001 From: Hyeonwoo Kim <31983961+ASak1104@users.noreply.github.com> Date: Fri, 24 Nov 2023 16:55:56 +0900 Subject: [PATCH 73/73] docs: fix typo --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 2e51d59c56..f20a049ac5 100644 --- a/README.md +++ b/README.md @@ -54,10 +54,10 @@ $ gradle test ## Run Locally -Clone the project branch `ASak1104/week2` +Clone the project branch `ASak1104/week3` ```bash -$ git clone -b ASak1104/week2 https://github.com/ASak1104/voucher-management-system.git +$ git clone -b ASak1104/week3 https://github.com/ASak1104/voucher-management-system.git ``` Go to the project directory