From d404a92afbbae42c67ff1c59416c834ce4bee336 Mon Sep 17 00:00:00 2001 From: Jay Date: Thu, 2 Nov 2023 05:10:19 +0900 Subject: [PATCH 01/81] chore: add spring-boot-web dependency --- build.gradle | 1 + 1 file changed, 1 insertion(+) diff --git a/build.gradle b/build.gradle index ae92e0119f..3a8e7b3ba8 100644 --- a/build.gradle +++ b/build.gradle @@ -25,6 +25,7 @@ dependencies { testImplementation 'org.testcontainers:testcontainers:1.19.1' testImplementation 'org.testcontainers:mysql:1.19.1' testImplementation 'org.testcontainers:junit-jupiter:1.19.1' + implementation 'org.springframework.boot:spring-boot-starter-web:3.1.4' } test { From c943839578f567275cf355cf69487b5b98f93221 Mon Sep 17 00:00:00 2001 From: Jay Date: Thu, 2 Nov 2023 05:11:18 +0900 Subject: [PATCH 02/81] feat: implement profile conditions --- .../configuration/profiles/ConsoleCondition.java | 12 ++++++++++++ .../configuration/profiles/DBEnabledCondition.java | 12 ++++++++++++ .../configuration/profiles/FileEnabledCondition.java | 12 ++++++++++++ 3 files changed, 36 insertions(+) create mode 100644 src/main/java/com/programmers/vouchermanagement/configuration/profiles/ConsoleCondition.java create mode 100644 src/main/java/com/programmers/vouchermanagement/configuration/profiles/DBEnabledCondition.java create mode 100644 src/main/java/com/programmers/vouchermanagement/configuration/profiles/FileEnabledCondition.java diff --git a/src/main/java/com/programmers/vouchermanagement/configuration/profiles/ConsoleCondition.java b/src/main/java/com/programmers/vouchermanagement/configuration/profiles/ConsoleCondition.java new file mode 100644 index 0000000000..28592dfb9f --- /dev/null +++ b/src/main/java/com/programmers/vouchermanagement/configuration/profiles/ConsoleCondition.java @@ -0,0 +1,12 @@ +package com.programmers.vouchermanagement.configuration.profiles; + +import org.springframework.context.annotation.Condition; +import org.springframework.context.annotation.ConditionContext; +import org.springframework.core.type.AnnotatedTypeMetadata; + +public class ConsoleCondition implements Condition { + @Override + public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { + return context.getEnvironment().matchesProfiles("dev", "file", "jdbc"); + } +} diff --git a/src/main/java/com/programmers/vouchermanagement/configuration/profiles/DBEnabledCondition.java b/src/main/java/com/programmers/vouchermanagement/configuration/profiles/DBEnabledCondition.java new file mode 100644 index 0000000000..6dd2b905a8 --- /dev/null +++ b/src/main/java/com/programmers/vouchermanagement/configuration/profiles/DBEnabledCondition.java @@ -0,0 +1,12 @@ +package com.programmers.vouchermanagement.configuration.profiles; + +import org.springframework.context.annotation.Condition; +import org.springframework.context.annotation.ConditionContext; +import org.springframework.core.type.AnnotatedTypeMetadata; + +public class DBEnabledCondition implements Condition { + @Override + public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { + return context.getEnvironment().matchesProfiles("jdbc", "web"); + } +} diff --git a/src/main/java/com/programmers/vouchermanagement/configuration/profiles/FileEnabledCondition.java b/src/main/java/com/programmers/vouchermanagement/configuration/profiles/FileEnabledCondition.java new file mode 100644 index 0000000000..397945836b --- /dev/null +++ b/src/main/java/com/programmers/vouchermanagement/configuration/profiles/FileEnabledCondition.java @@ -0,0 +1,12 @@ +package com.programmers.vouchermanagement.configuration.profiles; + +import org.springframework.context.annotation.Condition; +import org.springframework.context.annotation.ConditionContext; +import org.springframework.core.type.AnnotatedTypeMetadata; + +public class FileEnabledCondition implements Condition { + @Override + public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { + return context.getEnvironment().matchesProfiles("file", "test"); + } +} From 52604fe621306c3aad523f98a219da0e6d0dec2d Mon Sep 17 00:00:00 2001 From: Jay Date: Thu, 2 Nov 2023 05:12:35 +0900 Subject: [PATCH 03/81] refactor: apply profile conditions usage --- .../vouchermanagement/configuration/DBConfig.java | 5 +++-- .../vouchermanagement/configuration/FileConfig.java | 5 +++-- .../properties/datasource/DataSourceProperties.java | 6 ++++-- .../vouchermanagement/consoleapp/runner/ConsoleApp.java | 5 +++-- .../customer/repository/FileCustomerRepository.java | 4 +++- .../customer/repository/JdbcCustomerRepository.java | 4 +++- .../voucher/repository/FileVoucherRepository.java | 4 +++- .../voucher/repository/JdbcVoucherRepository.java | 4 +++- .../resources/{application-jdbc.yaml => application.yaml} | 0 9 files changed, 25 insertions(+), 12 deletions(-) rename src/main/resources/{application-jdbc.yaml => application.yaml} (100%) diff --git a/src/main/java/com/programmers/vouchermanagement/configuration/DBConfig.java b/src/main/java/com/programmers/vouchermanagement/configuration/DBConfig.java index b96c88ee50..8a854f9760 100644 --- a/src/main/java/com/programmers/vouchermanagement/configuration/DBConfig.java +++ b/src/main/java/com/programmers/vouchermanagement/configuration/DBConfig.java @@ -4,15 +4,16 @@ import org.springframework.boot.jdbc.DataSourceBuilder; import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Conditional; import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Profile; import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; +import com.programmers.vouchermanagement.configuration.profiles.DBEnabledCondition; import com.programmers.vouchermanagement.configuration.properties.datasource.DataSourceProperties; import com.zaxxer.hikari.HikariDataSource; @Configuration -@Profile("jdbc") +@Conditional(DBEnabledCondition.class) public class DBConfig { @Bean public DataSource dataSource(DataSourceProperties dataSourceProperties) { diff --git a/src/main/java/com/programmers/vouchermanagement/configuration/FileConfig.java b/src/main/java/com/programmers/vouchermanagement/configuration/FileConfig.java index 78000a4f8f..377d9be576 100644 --- a/src/main/java/com/programmers/vouchermanagement/configuration/FileConfig.java +++ b/src/main/java/com/programmers/vouchermanagement/configuration/FileConfig.java @@ -3,16 +3,17 @@ import java.util.UUID; import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Conditional; import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Profile; import com.fasterxml.jackson.databind.ObjectMapper; +import com.programmers.vouchermanagement.configuration.profiles.FileEnabledCondition; import com.programmers.vouchermanagement.customer.domain.Customer; import com.programmers.vouchermanagement.util.JSONFileManager; import com.programmers.vouchermanagement.voucher.domain.Voucher; @Configuration -@Profile({"file", "test"}) +@Conditional(FileEnabledCondition.class) public class FileConfig { @Bean public ObjectMapper objectMapper() { diff --git a/src/main/java/com/programmers/vouchermanagement/configuration/properties/datasource/DataSourceProperties.java b/src/main/java/com/programmers/vouchermanagement/configuration/properties/datasource/DataSourceProperties.java index 4dcb918c77..25915c2013 100644 --- a/src/main/java/com/programmers/vouchermanagement/configuration/properties/datasource/DataSourceProperties.java +++ b/src/main/java/com/programmers/vouchermanagement/configuration/properties/datasource/DataSourceProperties.java @@ -2,9 +2,11 @@ import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.bind.ConstructorBinding; -import org.springframework.context.annotation.Profile; +import org.springframework.context.annotation.Conditional; -@Profile("jdbc") +import com.programmers.vouchermanagement.configuration.profiles.DBEnabledCondition; + +@Conditional(DBEnabledCondition.class) @ConfigurationProperties("datasource") public class DataSourceProperties { private final String driverClassName; diff --git a/src/main/java/com/programmers/vouchermanagement/consoleapp/runner/ConsoleApp.java b/src/main/java/com/programmers/vouchermanagement/consoleapp/runner/ConsoleApp.java index 26fbd721d5..b224e3d3bd 100644 --- a/src/main/java/com/programmers/vouchermanagement/consoleapp/runner/ConsoleApp.java +++ b/src/main/java/com/programmers/vouchermanagement/consoleapp/runner/ConsoleApp.java @@ -4,15 +4,16 @@ import org.slf4j.LoggerFactory; import org.springframework.boot.ApplicationArguments; import org.springframework.boot.ApplicationRunner; -import org.springframework.context.annotation.Profile; +import org.springframework.context.annotation.Conditional; import org.springframework.stereotype.Component; +import com.programmers.vouchermanagement.configuration.profiles.ConsoleCondition; import com.programmers.vouchermanagement.consoleapp.io.ConsoleManager; import com.programmers.vouchermanagement.consoleapp.menu.Menu; import com.programmers.vouchermanagement.consoleapp.menu.MenuHandler; @Component -@Profile({"jdbc, dev, file"}) +@Conditional(ConsoleCondition.class) public class ConsoleApp implements ApplicationRunner { private static final Logger logger = LoggerFactory.getLogger(ConsoleApp.class); private static final String INCORRECT_MESSAGE = "Selected menu is not an executable menu."; diff --git a/src/main/java/com/programmers/vouchermanagement/customer/repository/FileCustomerRepository.java b/src/main/java/com/programmers/vouchermanagement/customer/repository/FileCustomerRepository.java index 4178761606..737adabdbe 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/repository/FileCustomerRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/repository/FileCustomerRepository.java @@ -9,16 +9,18 @@ import java.util.function.Function; import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.context.annotation.Conditional; import org.springframework.context.annotation.Profile; import org.springframework.stereotype.Repository; +import com.programmers.vouchermanagement.configuration.profiles.FileEnabledCondition; import com.programmers.vouchermanagement.configuration.properties.file.FileProperties; import com.programmers.vouchermanagement.customer.domain.Customer; import com.programmers.vouchermanagement.customer.domain.CustomerType; import com.programmers.vouchermanagement.util.JSONFileManager; @Repository -@Profile({"file", "test"}) +@Conditional(FileEnabledCondition.class) public class FileCustomerRepository implements CustomerRepository { private static final String CUSTOMER_ID_KEY = "customerId"; private static final String NAME_KEY = "name"; diff --git a/src/main/java/com/programmers/vouchermanagement/customer/repository/JdbcCustomerRepository.java b/src/main/java/com/programmers/vouchermanagement/customer/repository/JdbcCustomerRepository.java index b1dbaee74c..a420cfa56d 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/repository/JdbcCustomerRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/repository/JdbcCustomerRepository.java @@ -10,19 +10,21 @@ import java.util.Optional; import java.util.UUID; +import org.springframework.context.annotation.Conditional; import org.springframework.context.annotation.Profile; import org.springframework.dao.EmptyResultDataAccessException; import org.springframework.jdbc.core.RowMapper; import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; import org.springframework.stereotype.Repository; +import com.programmers.vouchermanagement.configuration.profiles.DBEnabledCondition; import com.programmers.vouchermanagement.configuration.properties.file.FileProperties; import com.programmers.vouchermanagement.customer.domain.Customer; import com.programmers.vouchermanagement.customer.domain.CustomerType; import com.programmers.vouchermanagement.util.UUIDConverter; @Repository -@Profile("jdbc") +@Conditional(DBEnabledCondition.class) public class JdbcCustomerRepository implements CustomerRepository { private static final RowMapper customerRowMapper = (resultSet, i) -> mapToCustomer(resultSet); public static final int SINGLE_DATA_FLAG = 1; diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/repository/FileVoucherRepository.java b/src/main/java/com/programmers/vouchermanagement/voucher/repository/FileVoucherRepository.java index 0648c92c3a..42b324bb1f 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/repository/FileVoucherRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/repository/FileVoucherRepository.java @@ -10,16 +10,18 @@ import java.util.function.Function; import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.context.annotation.Conditional; import org.springframework.context.annotation.Profile; import org.springframework.stereotype.Repository; +import com.programmers.vouchermanagement.configuration.profiles.FileEnabledCondition; import com.programmers.vouchermanagement.configuration.properties.file.FileProperties; import com.programmers.vouchermanagement.util.JSONFileManager; import com.programmers.vouchermanagement.voucher.domain.Voucher; import com.programmers.vouchermanagement.voucher.domain.VoucherType; @Repository -@Profile({"file", "test"}) +@Conditional(FileEnabledCondition.class) public class FileVoucherRepository implements VoucherRepository { //constants private static final String VOUCHER_ID_KEY = "voucher_id"; diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/repository/JdbcVoucherRepository.java b/src/main/java/com/programmers/vouchermanagement/voucher/repository/JdbcVoucherRepository.java index 083fb2f2f4..8c0e2d0ad7 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/repository/JdbcVoucherRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/repository/JdbcVoucherRepository.java @@ -11,18 +11,20 @@ import java.util.Optional; import java.util.UUID; +import org.springframework.context.annotation.Conditional; import org.springframework.context.annotation.Profile; import org.springframework.dao.EmptyResultDataAccessException; import org.springframework.jdbc.core.RowMapper; import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; import org.springframework.stereotype.Repository; +import com.programmers.vouchermanagement.configuration.profiles.DBEnabledCondition; import com.programmers.vouchermanagement.util.UUIDConverter; import com.programmers.vouchermanagement.voucher.domain.Voucher; import com.programmers.vouchermanagement.voucher.domain.VoucherType; @Repository -@Profile("jdbc") +@Conditional(DBEnabledCondition.class) public class JdbcVoucherRepository implements VoucherRepository { private static final int SINGLE_DATA_FLAG = 1; diff --git a/src/main/resources/application-jdbc.yaml b/src/main/resources/application.yaml similarity index 100% rename from src/main/resources/application-jdbc.yaml rename to src/main/resources/application.yaml From 7712ce8d2c3b3814c1da49b05b0333cb5d7b49a8 Mon Sep 17 00:00:00 2001 From: Jay Date: Thu, 2 Nov 2023 05:13:13 +0900 Subject: [PATCH 04/81] feat: add voucher rest controller --- .../controller/VoucherRestController.java | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherRestController.java diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherRestController.java b/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherRestController.java new file mode 100644 index 0000000000..603e422159 --- /dev/null +++ b/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherRestController.java @@ -0,0 +1,47 @@ +package com.programmers.vouchermanagement.voucher.controller; + +import java.util.List; +import java.util.UUID; + +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.RestController; + +import com.programmers.vouchermanagement.voucher.dto.CreateVoucherRequest; +import com.programmers.vouchermanagement.voucher.dto.VoucherResponse; +import com.programmers.vouchermanagement.voucher.service.VoucherService; + +@RestController +@RequestMapping("/api/v1/vouchers") +public class VoucherRestController { + private final VoucherService voucherService; + + public VoucherRestController(VoucherService voucherService) { + this.voucherService = voucherService; + } + + @PostMapping + public VoucherResponse create(CreateVoucherRequest createVoucherRequest) { + return voucherService.create(createVoucherRequest); + } + + @GetMapping("/{voucherId}") + public VoucherResponse findById(@PathVariable UUID voucherId) { + return voucherService.findById(voucherId); + } + + @GetMapping + public List readAllVouchers() { + return voucherService.readAllVouchers(); + } + + //TODO: 조건별 조회 추가 + + @DeleteMapping("/{voucherId}") + public void deleteById(@PathVariable UUID voucherId) { + voucherService.deleteById(voucherId); + } +} From 9eeab5461be0b9dfe592edcf696ce1a9653a9c26 Mon Sep 17 00:00:00 2001 From: Jay Date: Thu, 2 Nov 2023 09:36:33 +0900 Subject: [PATCH 05/81] refactor: decide to add percentage mark in formatter --- .../vouchermanagement/util/Formatter.java | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/util/Formatter.java b/src/main/java/com/programmers/vouchermanagement/util/Formatter.java index a5d79a1b40..9d229fb517 100644 --- a/src/main/java/com/programmers/vouchermanagement/util/Formatter.java +++ b/src/main/java/com/programmers/vouchermanagement/util/Formatter.java @@ -1,6 +1,7 @@ package com.programmers.vouchermanagement.util; import com.programmers.vouchermanagement.customer.dto.CustomerResponse; +import com.programmers.vouchermanagement.voucher.domain.VoucherType; import com.programmers.vouchermanagement.voucher.dto.VoucherResponse; public class Formatter { @@ -23,8 +24,6 @@ private Formatter() { Discount Amount : %s -------------------------"""; - //messages - public static String formatNoContent(String contentType) { return NO_CONTENT.formatted(contentType); } @@ -36,9 +35,16 @@ public static String formatCustomer(CustomerResponse customerResponse) { public static String formatVoucher(VoucherResponse voucherResponse) { return VOUCHER_PRESENTATION_FORMAT - .formatted(voucherResponse.getVoucherId(), - voucherResponse.getVoucherTypeName(), - voucherResponse.getDiscountValue() + - (voucherResponse.isPercentVoucher() ? PERCENTAGE : EMPTY)); + .formatted(voucherResponse.voucherId(), + voucherResponse.voucherType(), + voucherResponse.discountValue() + + markPercentage(voucherResponse.voucherType())); + } + + private static String markPercentage(VoucherType voucherType) { + if (voucherType.isPercent()) { + return PERCENTAGE; + } + return EMPTY; } } From 4bba969ea3582d1f59b1401d3877fdd2468a4aeb Mon Sep 17 00:00:00 2001 From: Jay Date: Thu, 2 Nov 2023 09:37:34 +0900 Subject: [PATCH 06/81] refactor: make VoucherResponse a record --- .../consoleapp/io/ConsoleManager.java | 2 +- .../voucher/dto/VoucherResponse.java | 45 +++---------------- .../voucher/service/VoucherService.java | 4 +- .../controller/VoucherControllerTest.java | 10 ++--- .../voucher/service/VoucherServiceTest.java | 4 +- 5 files changed, 17 insertions(+), 48 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/consoleapp/io/ConsoleManager.java b/src/main/java/com/programmers/vouchermanagement/consoleapp/io/ConsoleManager.java index 07f44f35c9..6504bcd9c2 100644 --- a/src/main/java/com/programmers/vouchermanagement/consoleapp/io/ConsoleManager.java +++ b/src/main/java/com/programmers/vouchermanagement/consoleapp/io/ConsoleManager.java @@ -152,7 +152,7 @@ public VoucherCustomerRequest instructRequestVoucherCustomer() { } public void printSaveVoucherResult(VoucherResponse voucherResponse) { - print(CREATE_SUCCESS_MESSAGE.formatted(CONTENT_VOUCHER, voucherResponse.getVoucherId())); + print(CREATE_SUCCESS_MESSAGE.formatted(CONTENT_VOUCHER, voucherResponse.voucherId())); } public void printSaveCustomerResult(CustomerResponse customerResponse) { diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/dto/VoucherResponse.java b/src/main/java/com/programmers/vouchermanagement/voucher/dto/VoucherResponse.java index 0a14338d04..eb8ac2480b 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/dto/VoucherResponse.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/dto/VoucherResponse.java @@ -6,44 +6,13 @@ import com.programmers.vouchermanagement.voucher.domain.Voucher; import com.programmers.vouchermanagement.voucher.domain.VoucherType; -public class VoucherResponse { - private final UUID voucherId; - private final BigDecimal discountValue; - private final VoucherType voucherType; - private final UUID customerId; - - private VoucherResponse(UUID voucherId, BigDecimal discountValue, VoucherType voucherType, UUID customerId) { - this.voucherId = voucherId; - this.discountValue = discountValue; - this.voucherType = voucherType; - this.customerId = customerId; - } - +public record VoucherResponse(UUID voucherId, BigDecimal discountValue, VoucherType voucherType, UUID customerId) { public static VoucherResponse from(Voucher voucher) { - return new VoucherResponse(voucher.getVoucherId(), voucher.getDiscountValue(), voucher.getVoucherType(), voucher.getCustomerId()); - } - - public UUID getVoucherId() { - return voucherId; - } - - public BigDecimal getDiscountValue() { - return discountValue; - } - - public UUID getCustomerId() { - return customerId; - } - - public VoucherType getVoucherType() { - return voucherType; - } - - public boolean isPercentVoucher() { - return voucherType.isPercent(); - } - - public String getVoucherTypeName() { - return voucherType.displayTypeName(); + return new VoucherResponse( + voucher.getVoucherId(), + voucher.getDiscountValue(), + voucher.getVoucherType(), + voucher.getCustomerId() + ); } } diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java b/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java index 71d473e80b..5fa2b546b9 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java @@ -59,14 +59,14 @@ public void deleteById(UUID voucherId) { public void grantToCustomer(VoucherCustomerRequest request) { validateCustomerIdExisting(request.customerId()); VoucherResponse foundVoucher = findById(request.voucherId()); - Voucher voucher = new Voucher(request.voucherId(), foundVoucher.getDiscountValue(), foundVoucher.getVoucherType(), request.customerId()); + Voucher voucher = new Voucher(request.voucherId(), foundVoucher.discountValue(), foundVoucher.voucherType(), request.customerId()); voucherRepository.save(voucher); } public void releaseFromCustomer(VoucherCustomerRequest request) { validateCustomerIdExisting(request.customerId()); VoucherResponse foundVoucher = findById(request.voucherId()); - Voucher voucher = new Voucher(foundVoucher.getVoucherId(), foundVoucher.getDiscountValue(), foundVoucher.getVoucherType()); + Voucher voucher = new Voucher(foundVoucher.voucherId(), foundVoucher.discountValue(), foundVoucher.voucherType()); voucherRepository.save(voucher); } diff --git a/src/test/java/com/programmers/vouchermanagement/voucher/controller/VoucherControllerTest.java b/src/test/java/com/programmers/vouchermanagement/voucher/controller/VoucherControllerTest.java index 54d11ebadf..ef2de3ee2d 100644 --- a/src/test/java/com/programmers/vouchermanagement/voucher/controller/VoucherControllerTest.java +++ b/src/test/java/com/programmers/vouchermanagement/voucher/controller/VoucherControllerTest.java @@ -58,7 +58,7 @@ void testCreateVoucher_ViewShowingCreatedVoucher() { //then UUID createdCVoucherId = voucherService.readAllVouchers() .stream() - .map(VoucherResponse::getVoucherId) + .map(VoucherResponse::voucherId) .findFirst() .orElse(UUID.randomUUID()); assertThat(output, containsString(createdCVoucherId.toString())); @@ -93,7 +93,7 @@ void testReadAllVouchers_ViewShowingVouchers() { //then UUID foundVoucherId = voucherService.readAllVouchers() .stream() - .map(VoucherResponse::getVoucherId) + .map(VoucherResponse::voucherId) .findFirst() .orElse(UUID.randomUUID()); assertThat(output, containsString("Voucher ID : " + foundVoucherId)); @@ -120,7 +120,7 @@ void testUpdateVoucher_ViewShowingUpdatedVoucher() { //given CreateVoucherRequest createRequest = new CreateVoucherRequest(new BigDecimal(10000), VoucherType.FIXED); VoucherResponse voucher = voucherService.create(createRequest); - UpdateVoucherRequest updateRequest = new UpdateVoucherRequest(voucher.getVoucherId(), new BigDecimal(20000), VoucherType.FIXED); + UpdateVoucherRequest updateRequest = new UpdateVoucherRequest(voucher.voucherId(), new BigDecimal(20000), VoucherType.FIXED); //when voucherController.update(updateRequest); @@ -139,7 +139,7 @@ void testDeleteVoucherById_SuccessfullyDeleted() { VoucherResponse voucher = voucherService.create(createRequest); //when - voucherController.deleteById(voucher.getVoucherId()); + voucherController.deleteById(voucher.voucherId()); String output = textTerminal.getOutput(); //then @@ -154,7 +154,7 @@ void testGrantVoucherToCustomer_SuccessfullyGranted() { VoucherResponse voucher = voucherService.create(createRequest); Customer customer = new Customer(UUID.randomUUID(), "test-customer"); customerRepository.save(customer); - VoucherCustomerRequest request = new VoucherCustomerRequest(voucher.getVoucherId(), customer.getCustomerId()); + VoucherCustomerRequest request = new VoucherCustomerRequest(voucher.voucherId(), customer.getCustomerId()); //when voucherController.grantToCustomer(request); diff --git a/src/test/java/com/programmers/vouchermanagement/voucher/service/VoucherServiceTest.java b/src/test/java/com/programmers/vouchermanagement/voucher/service/VoucherServiceTest.java index 8f0ee0c89c..f8f7bbd21f 100644 --- a/src/test/java/com/programmers/vouchermanagement/voucher/service/VoucherServiceTest.java +++ b/src/test/java/com/programmers/vouchermanagement/voucher/service/VoucherServiceTest.java @@ -59,7 +59,7 @@ void testFixedVoucherCreationSuccessful() { VoucherResponse voucher = voucherService.create(request); //then - Voucher createdVoucher = voucherRepository.findById(voucher.getVoucherId()) + Voucher createdVoucher = voucherRepository.findById(voucher.voucherId()) .get(); assertThat(VoucherResponse.from(createdVoucher), samePropertyValuesAs(voucher)); } @@ -90,7 +90,7 @@ void textPercentVoucherCreationSuccessful() { VoucherResponse voucher = voucherService.create(request); //then - Voucher createdVoucher = voucherRepository.findById(voucher.getVoucherId()) + Voucher createdVoucher = voucherRepository.findById(voucher.voucherId()) .get(); assertThat(VoucherResponse.from(createdVoucher), samePropertyValuesAs(voucher)); } From 29353f99613eb884c82181714ddc173c658c2e94 Mon Sep 17 00:00:00 2001 From: Jay Date: Thu, 2 Nov 2023 10:05:12 +0900 Subject: [PATCH 07/81] enhance: add createdAt to Voucher --- .../vouchermanagement/util/Formatter.java | 2 ++ .../voucher/domain/Voucher.java | 11 +++++++++-- .../voucher/dto/VoucherResponse.java | 10 +++++++++- .../repository/FileVoucherRepository.java | 6 +++++- .../repository/JdbcVoucherRepository.java | 9 +++++++-- .../voucher/service/VoucherService.java | 16 ++++++++++++++-- src/test/resources/init.sql | 1 + 7 files changed, 47 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/util/Formatter.java b/src/main/java/com/programmers/vouchermanagement/util/Formatter.java index 9d229fb517..dd0f2b0689 100644 --- a/src/main/java/com/programmers/vouchermanagement/util/Formatter.java +++ b/src/main/java/com/programmers/vouchermanagement/util/Formatter.java @@ -20,6 +20,7 @@ private Formatter() { -------------------------"""; private static final String VOUCHER_PRESENTATION_FORMAT = """ Voucher ID : %s + Creation Datetime : %s Voucher Type : %s Discount Voucher Discount Amount : %s -------------------------"""; @@ -36,6 +37,7 @@ public static String formatCustomer(CustomerResponse customerResponse) { public static String formatVoucher(VoucherResponse voucherResponse) { return VOUCHER_PRESENTATION_FORMAT .formatted(voucherResponse.voucherId(), + voucherResponse.createdAt(), voucherResponse.voucherType(), voucherResponse.discountValue() + markPercentage(voucherResponse.voucherType())); diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/domain/Voucher.java b/src/main/java/com/programmers/vouchermanagement/voucher/domain/Voucher.java index 61af09a92a..9029c99b74 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/domain/Voucher.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/domain/Voucher.java @@ -1,21 +1,24 @@ package com.programmers.vouchermanagement.voucher.domain; import java.math.BigDecimal; +import java.time.LocalDateTime; import java.util.UUID; public class Voucher { private final UUID voucherId; + private final LocalDateTime createdAt; private final BigDecimal discountValue; private final VoucherType voucherType; private final UUID customerId; public Voucher(UUID voucherId, BigDecimal discountValue, VoucherType voucherType) { - this(voucherId, discountValue, voucherType, null); + this(voucherId, LocalDateTime.now(), discountValue, voucherType, null); } - public Voucher(UUID voucherId, BigDecimal discountValue, VoucherType voucherType, UUID customerId) { + public Voucher(UUID voucherId, LocalDateTime createdAt, BigDecimal discountValue, VoucherType voucherType, UUID customerId) { voucherType.validateDiscountValue(discountValue); this.voucherId = voucherId; + this.createdAt = createdAt; this.voucherType = voucherType; this.discountValue = discountValue; this.customerId = customerId; @@ -25,6 +28,10 @@ public UUID getVoucherId() { return voucherId; } + public LocalDateTime getCreatedAt() { + return createdAt; + } + public BigDecimal getDiscountValue() { return discountValue; } diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/dto/VoucherResponse.java b/src/main/java/com/programmers/vouchermanagement/voucher/dto/VoucherResponse.java index eb8ac2480b..1cb91ebda2 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/dto/VoucherResponse.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/dto/VoucherResponse.java @@ -1,15 +1,23 @@ package com.programmers.vouchermanagement.voucher.dto; import java.math.BigDecimal; +import java.time.LocalDateTime; import java.util.UUID; import com.programmers.vouchermanagement.voucher.domain.Voucher; import com.programmers.vouchermanagement.voucher.domain.VoucherType; -public record VoucherResponse(UUID voucherId, BigDecimal discountValue, VoucherType voucherType, UUID customerId) { +public record VoucherResponse( + UUID voucherId, + LocalDateTime createdAt, + BigDecimal discountValue, + VoucherType voucherType, + UUID customerId +) { public static VoucherResponse from(Voucher voucher) { return new VoucherResponse( voucher.getVoucherId(), + voucher.getCreatedAt(), voucher.getDiscountValue(), voucher.getVoucherType(), voucher.getCustomerId() diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/repository/FileVoucherRepository.java b/src/main/java/com/programmers/vouchermanagement/voucher/repository/FileVoucherRepository.java index 42b324bb1f..956c37eeb0 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/repository/FileVoucherRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/repository/FileVoucherRepository.java @@ -1,6 +1,7 @@ package com.programmers.vouchermanagement.voucher.repository; import java.math.BigDecimal; +import java.time.LocalDateTime; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -25,6 +26,7 @@ public class FileVoucherRepository implements VoucherRepository { //constants private static final String VOUCHER_ID_KEY = "voucher_id"; + private static final String VOUCHER_CREATED_AT_KEY = "created_at"; private static final String DISCOUNT_VALUE_KEY = "discount_value"; private static final String VOUCHER_TYPE_KEY = "voucher_type"; private static final String CUSTOMER_ID_KEY = "customer_id"; @@ -35,16 +37,18 @@ public class FileVoucherRepository implements VoucherRepository { private final Function objectToVoucher = (voucherObject) -> { UUID voucherId = UUID.fromString(String.valueOf(voucherObject.get(VOUCHER_ID_KEY))); + LocalDateTime createdAt = LocalDateTime.parse(String.valueOf(voucherObject.get(VOUCHER_CREATED_AT_KEY))); BigDecimal discountValue = new BigDecimal(String.valueOf(voucherObject.get(DISCOUNT_VALUE_KEY))); String voucherTypeName = String.valueOf(voucherObject.get(VOUCHER_TYPE_KEY)); VoucherType voucherType = VoucherType.findVoucherTypeByName(voucherTypeName); String customerIdString = String.valueOf(voucherObject.get(CUSTOMER_ID_KEY)); UUID customerId = customerIdString.equals("null") ? null : UUID.fromString(customerIdString); - return new Voucher(voucherId, discountValue, voucherType, customerId); + return new Voucher(voucherId, createdAt, discountValue, voucherType, customerId); }; private final Function> voucherToObject = (voucher) -> { HashMap voucherObject = new HashMap<>(); voucherObject.put(VOUCHER_ID_KEY, voucher.getVoucherId().toString()); + voucherObject.put(VOUCHER_CREATED_AT_KEY, voucher.getCreatedAt()); voucherObject.put(DISCOUNT_VALUE_KEY, voucher.getDiscountValue().toString()); voucherObject.put(VOUCHER_TYPE_KEY, voucher.getVoucherType().name()); voucherObject.put(CUSTOMER_ID_KEY, voucher.getCustomerId()); diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/repository/JdbcVoucherRepository.java b/src/main/java/com/programmers/vouchermanagement/voucher/repository/JdbcVoucherRepository.java index 8c0e2d0ad7..e5dd5be784 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/repository/JdbcVoucherRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/repository/JdbcVoucherRepository.java @@ -3,6 +3,8 @@ import java.math.BigDecimal; import java.sql.ResultSet; import java.sql.SQLException; +import java.sql.Timestamp; +import java.time.LocalDateTime; import java.util.Collections; import java.util.HashMap; import java.util.List; @@ -82,7 +84,7 @@ public void deleteAll() { } private int insert(Voucher voucher) { - String saveSQL = "INSERT INTO vouchers(voucher_id, discount_value, voucher_type) VALUES (UUID_TO_BIN(:voucherId), :discountValue, :voucherType)"; + String saveSQL = "INSERT INTO vouchers(voucher_id, created_at, discount_value, voucher_type) VALUES (UUID_TO_BIN(:voucherId), :createdAt, :discountValue, :voucherType)"; Map parameterMap = toParameterMap(voucher); return namedParameterJdbcTemplate.update(saveSQL, parameterMap); } @@ -96,19 +98,22 @@ private int update(Voucher voucher) { private Map toParameterMap(Voucher voucher) { Map parameterMap = new HashMap<>(); parameterMap.put("voucherId", voucher.getVoucherId().toString().getBytes()); + parameterMap.put("createdAt", Timestamp.valueOf(voucher.getCreatedAt())); parameterMap.put("discountValue", voucher.getDiscountValue()); parameterMap.put("voucherType", voucher.getVoucherType().name()); + parameterMap.put("customerId", voucher.getCustomerId()); return Collections.unmodifiableMap(parameterMap); } private static Voucher mapToVoucher(ResultSet resultSet) throws SQLException { final UUID voucherId = UUIDConverter.from(resultSet.getBytes("voucher_id")); + final LocalDateTime createdAt = resultSet.getTimestamp("created_at").toLocalDateTime(); final BigDecimal discountValue = resultSet.getBigDecimal("discount_value"); final String voucherTypeName = resultSet.getString("voucher_type"); final VoucherType voucherType = VoucherType.findVoucherTypeByName(voucherTypeName); byte[] idBytes = resultSet.getBytes("customer_id"); final UUID customerId = idBytes != null ? UUIDConverter.from(idBytes) : null; - return new Voucher(voucherId, discountValue, voucherType, customerId); + return new Voucher(voucherId, createdAt, discountValue, voucherType, customerId); } } diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java b/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java index 5fa2b546b9..92cb0157bc 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java @@ -59,14 +59,26 @@ public void deleteById(UUID voucherId) { public void grantToCustomer(VoucherCustomerRequest request) { validateCustomerIdExisting(request.customerId()); VoucherResponse foundVoucher = findById(request.voucherId()); - Voucher voucher = new Voucher(request.voucherId(), foundVoucher.discountValue(), foundVoucher.voucherType(), request.customerId()); + Voucher voucher = new Voucher( + request.voucherId(), + foundVoucher.createdAt(), + foundVoucher.discountValue(), + foundVoucher.voucherType(), + request.customerId() + ); voucherRepository.save(voucher); } public void releaseFromCustomer(VoucherCustomerRequest request) { validateCustomerIdExisting(request.customerId()); VoucherResponse foundVoucher = findById(request.voucherId()); - Voucher voucher = new Voucher(foundVoucher.voucherId(), foundVoucher.discountValue(), foundVoucher.voucherType()); + Voucher voucher = new Voucher( + foundVoucher.voucherId(), + foundVoucher.createdAt(), + foundVoucher.discountValue(), + foundVoucher.voucherType(), + null + ); voucherRepository.save(voucher); } diff --git a/src/test/resources/init.sql b/src/test/resources/init.sql index 4c77b60154..3d08a794ca 100644 --- a/src/test/resources/init.sql +++ b/src/test/resources/init.sql @@ -6,6 +6,7 @@ CREATE TABLE customers ( CREATE TABLE vouchers ( voucher_id BINARY(16) PRIMARY KEY, + created_at DATETIME NOT NULL, discount_value DECIMAL NOT NULL, voucher_type VARCHAR(10) NOT NULL, customer_id BINARY(16), From 1b9c323844e46c64f1a5b28c7d55ba0130132740 Mon Sep 17 00:00:00 2001 From: Jay Date: Thu, 2 Nov 2023 10:05:45 +0900 Subject: [PATCH 08/81] chore: reset file --- src/main/resources/voucher.json | 11 ----------- src/test/resources/voucher-test.json | 26 -------------------------- 2 files changed, 37 deletions(-) diff --git a/src/main/resources/voucher.json b/src/main/resources/voucher.json index f3e4bd30db..e69de29bb2 100644 --- a/src/main/resources/voucher.json +++ b/src/main/resources/voucher.json @@ -1,11 +0,0 @@ -[ { - "voucher_type" : "FIXED", - "voucher_id" : "4b10670f-5fcc-4b05-ba9c-c7972411c1fb", - "discount_value" : "1000", - "customer_id" : null -}, { - "voucher_type" : "FIXED", - "voucher_id" : "4580ed30-4725-481a-807b-feeeccd5cd06", - "discount_value" : "10000", - "customer_id" : null -} ] diff --git a/src/test/resources/voucher-test.json b/src/test/resources/voucher-test.json index d5860173e7..e69de29bb2 100644 --- a/src/test/resources/voucher-test.json +++ b/src/test/resources/voucher-test.json @@ -1,26 +0,0 @@ -[ { - "voucher_type" : "PERCENT", - "voucher_id" : "11dd24b8-95af-4634-a8c7-b12cfe2c389a", - "discount_value" : "50", - "customer_id" : null -}, { - "voucher_type" : "PERCENT", - "voucher_id" : "56096331-5d50-4c62-9951-80c905e61ba1", - "discount_value" : "50", - "customer_id" : null -}, { - "voucher_type" : "FIXED", - "voucher_id" : "7e5ca090-27fe-4e62-844e-0a64557bcb7a", - "discount_value" : "10000", - "customer_id" : null -}, { - "voucher_type" : "FIXED", - "voucher_id" : "f470205b-c64a-448f-ad83-46497ceb8833", - "discount_value" : "5000", - "customer_id" : null -}, { - "voucher_type" : "PERCENT", - "voucher_id" : "bae97b45-a4f8-4a55-8eee-c455f9a63322", - "discount_value" : "40", - "customer_id" : null -} ] \ No newline at end of file From b39904fc644fd733fdf95fac67453f4d00b0f50d Mon Sep 17 00:00:00 2001 From: Jay Date: Thu, 2 Nov 2023 10:54:53 +0900 Subject: [PATCH 09/81] feat: tell if the input is the same type of the voucher --- .../vouchermanagement/voucher/domain/Voucher.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/domain/Voucher.java b/src/main/java/com/programmers/vouchermanagement/voucher/domain/Voucher.java index 9029c99b74..480ad4a3de 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/domain/Voucher.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/domain/Voucher.java @@ -15,6 +15,10 @@ public Voucher(UUID voucherId, BigDecimal discountValue, VoucherType voucherType this(voucherId, LocalDateTime.now(), discountValue, voucherType, null); } + public Voucher(UUID voucherId, BigDecimal discountValue, VoucherType voucherType, UUID customerId) { + this(voucherId, LocalDateTime.now(), discountValue, voucherType, customerId); + } + public Voucher(UUID voucherId, LocalDateTime createdAt, BigDecimal discountValue, VoucherType voucherType, UUID customerId) { voucherType.validateDiscountValue(discountValue); this.voucherId = voucherId; @@ -47,4 +51,8 @@ public UUID getCustomerId() { public boolean isOwned() { return this.customerId != null; } + + public boolean isSameType(VoucherType voucherType) { + return this.voucherType == voucherType; + } } From a46bb3283e720a1c16328de00d35a7770104c034 Mon Sep 17 00:00:00 2001 From: Jay Date: Thu, 2 Nov 2023 10:55:41 +0900 Subject: [PATCH 10/81] feat: add findByType in repositories --- .../voucher/repository/FileVoucherRepository.java | 8 ++++++++ .../voucher/repository/InMemoryVoucherRepository.java | 9 +++++++++ .../voucher/repository/JdbcVoucherRepository.java | 7 +++++++ .../voucher/repository/VoucherRepository.java | 2 ++ 4 files changed, 26 insertions(+) diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/repository/FileVoucherRepository.java b/src/main/java/com/programmers/vouchermanagement/voucher/repository/FileVoucherRepository.java index 956c37eeb0..3d12d61784 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/repository/FileVoucherRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/repository/FileVoucherRepository.java @@ -76,6 +76,14 @@ public List findAll() { .toList(); } + @Override + public List findByType(VoucherType voucherType) { + return vouchers.values() + .stream() + .filter(voucher -> voucher.isSameType(voucherType)) + .toList(); + } + @Override public Optional findById(UUID voucherId) { return Optional.ofNullable(vouchers.get(voucherId)); diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/repository/InMemoryVoucherRepository.java b/src/main/java/com/programmers/vouchermanagement/voucher/repository/InMemoryVoucherRepository.java index 4350975b84..6c06d3ad42 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/repository/InMemoryVoucherRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/repository/InMemoryVoucherRepository.java @@ -11,6 +11,7 @@ import org.springframework.stereotype.Repository; import com.programmers.vouchermanagement.voucher.domain.Voucher; +import com.programmers.vouchermanagement.voucher.domain.VoucherType; @Repository @Profile("dev") @@ -32,6 +33,14 @@ public List findAll() { return vouchers.values().stream().toList(); } + @Override + public List findByType(VoucherType voucherType) { + return vouchers.values() + .stream() + .filter(voucher -> voucher.isSameType(voucherType)) + .toList(); + } + @Override public Optional findById(UUID voucherId) { return Optional.ofNullable(vouchers.get(voucherId)); diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/repository/JdbcVoucherRepository.java b/src/main/java/com/programmers/vouchermanagement/voucher/repository/JdbcVoucherRepository.java index e5dd5be784..45900fa798 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/repository/JdbcVoucherRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/repository/JdbcVoucherRepository.java @@ -53,6 +53,13 @@ public List findAll() { return Collections.unmodifiableList(namedParameterJdbcTemplate.query(findAllSQL, voucherRowMapper)); } + @Override + public List findByType(VoucherType voucherType) { + String findByTypeSQL = "SELECT * FROM vouchers WHERE voucher_type=(:voucherType)"; + Map parameterMap = Collections.singletonMap("voucherType", voucherType.name()); + return namedParameterJdbcTemplate.query(findByTypeSQL, parameterMap, voucherRowMapper); + } + @Override public Optional findById(UUID voucherId) { String findByIdSQL = "SELECT * FROM vouchers WHERE voucher_id=UUID_TO_BIN(:voucherId)"; diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherRepository.java b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherRepository.java index 542e0411d6..8a1bc6c468 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherRepository.java @@ -5,10 +5,12 @@ import java.util.UUID; import com.programmers.vouchermanagement.voucher.domain.Voucher; +import com.programmers.vouchermanagement.voucher.domain.VoucherType; public interface VoucherRepository { Voucher save(Voucher voucher); List findAll(); + List findByType(VoucherType voucherType); Optional findById(UUID voucherId); List findByCustomerId(UUID customerId); void deleteById(UUID voucherId); From 85a4cfa72c75f62d2d4d926ba8f0508f69e2c2ad Mon Sep 17 00:00:00 2001 From: Jay Date: Thu, 2 Nov 2023 10:56:01 +0900 Subject: [PATCH 11/81] feat: implement findByType service --- .../vouchermanagement/voucher/service/VoucherService.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java b/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java index 92cb0157bc..aadf0982f1 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java @@ -9,6 +9,7 @@ import com.programmers.vouchermanagement.customer.domain.Customer; import com.programmers.vouchermanagement.customer.repository.CustomerRepository; import com.programmers.vouchermanagement.voucher.domain.Voucher; +import com.programmers.vouchermanagement.voucher.domain.VoucherType; import com.programmers.vouchermanagement.voucher.dto.CreateVoucherRequest; import com.programmers.vouchermanagement.voucher.dto.UpdateVoucherRequest; import com.programmers.vouchermanagement.voucher.dto.VoucherCustomerRequest; @@ -38,6 +39,13 @@ public List readAllVouchers() { .toList(); } + public List findByType(VoucherType voucherType) { + List vouchers = voucherRepository.findByType(voucherType); + return vouchers.stream() + .map(VoucherResponse::from) + .toList(); + } + public VoucherResponse findById(UUID voucherId) { Voucher voucher = voucherRepository.findById(voucherId) .orElseThrow(() -> new NoSuchElementException("There is no voucher with %s".formatted(voucherId))); From 7a3e0e8c935d0d09e18fe81cd7e0679df1c7269a Mon Sep 17 00:00:00 2001 From: Jay Date: Thu, 2 Nov 2023 10:56:15 +0900 Subject: [PATCH 12/81] feat: map to find vouchers by type --- .../controller/VoucherRestController.java | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherRestController.java b/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherRestController.java index 603e422159..fb4ffdf158 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherRestController.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherRestController.java @@ -10,6 +10,7 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; +import com.programmers.vouchermanagement.voucher.domain.VoucherType; import com.programmers.vouchermanagement.voucher.dto.CreateVoucherRequest; import com.programmers.vouchermanagement.voucher.dto.VoucherResponse; import com.programmers.vouchermanagement.voucher.service.VoucherService; @@ -28,20 +29,24 @@ public VoucherResponse create(CreateVoucherRequest createVoucherRequest) { return voucherService.create(createVoucherRequest); } - @GetMapping("/{voucherId}") - public VoucherResponse findById(@PathVariable UUID voucherId) { - return voucherService.findById(voucherId); - } - @GetMapping public List readAllVouchers() { return voucherService.readAllVouchers(); } - //TODO: 조건별 조회 추가 + @GetMapping("/{voucherId}") + public VoucherResponse findById(@PathVariable UUID voucherId) { + return voucherService.findById(voucherId); + } @DeleteMapping("/{voucherId}") public void deleteById(@PathVariable UUID voucherId) { voucherService.deleteById(voucherId); } + + @GetMapping("/type/{typeName}") + public List findByType(@PathVariable String typeName) { + VoucherType voucherType = VoucherType.findVoucherTypeByName(typeName); + return voucherService.findByType(voucherType); + } } From 5b9f5aa4797e6f37d56053f55782bb732a59bf3e Mon Sep 17 00:00:00 2001 From: Jay Date: Thu, 2 Nov 2023 21:22:09 +0900 Subject: [PATCH 13/81] feat: implemented to find vouchers by createdAt --- .../repository/FileVoucherRepository.java | 8 ++++++++ .../repository/InMemoryVoucherRepository.java | 9 +++++++++ .../repository/JdbcVoucherRepository.java | 9 +++++++++ .../voucher/repository/VoucherRepository.java | 4 +++- .../voucher/service/VoucherService.java | 19 +++++++++++++++++++ 5 files changed, 48 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/repository/FileVoucherRepository.java b/src/main/java/com/programmers/vouchermanagement/voucher/repository/FileVoucherRepository.java index 3d12d61784..9ccbf3404a 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/repository/FileVoucherRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/repository/FileVoucherRepository.java @@ -84,6 +84,14 @@ public List findByType(VoucherType voucherType) { .toList(); } + @Override + public List findByCreatedAt(LocalDateTime startDateTime, LocalDateTime endDateTime) { + return vouchers.values() + .stream() + .filter(voucher -> voucher.isCreatedInBetween(startDateTime, endDateTime)) + .toList(); + } + @Override public Optional findById(UUID voucherId) { return Optional.ofNullable(vouchers.get(voucherId)); diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/repository/InMemoryVoucherRepository.java b/src/main/java/com/programmers/vouchermanagement/voucher/repository/InMemoryVoucherRepository.java index 6c06d3ad42..f98dc668a6 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/repository/InMemoryVoucherRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/repository/InMemoryVoucherRepository.java @@ -1,5 +1,6 @@ package com.programmers.vouchermanagement.voucher.repository; +import java.time.LocalDateTime; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -41,6 +42,14 @@ public List findByType(VoucherType voucherType) { .toList(); } + @Override + public List findByCreatedAt(LocalDateTime startDateTime, LocalDateTime endDateTime) { + return vouchers.values() + .stream() + .filter(voucher -> voucher.isCreatedInBetween(startDateTime, endDateTime)) + .toList(); + } + @Override public Optional findById(UUID voucherId) { return Optional.ofNullable(vouchers.get(voucherId)); diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/repository/JdbcVoucherRepository.java b/src/main/java/com/programmers/vouchermanagement/voucher/repository/JdbcVoucherRepository.java index 45900fa798..5231aa8a92 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/repository/JdbcVoucherRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/repository/JdbcVoucherRepository.java @@ -60,6 +60,15 @@ public List findByType(VoucherType voucherType) { return namedParameterJdbcTemplate.query(findByTypeSQL, parameterMap, voucherRowMapper); } + @Override + public List findByCreatedAt(LocalDateTime startDateTime, LocalDateTime endDateTime) { + String findByCreatedAtSQL = "SELECT * FROM vouchers WHERE created_at BETWEEN :startDate AND :endDate"; + Map parameterMap = new HashMap<>(); + parameterMap.put("startDate", startDateTime); + parameterMap.put("endDate", endDateTime); + return namedParameterJdbcTemplate.query(findByCreatedAtSQL, Collections.unmodifiableMap(parameterMap), voucherRowMapper); + } + @Override public Optional findById(UUID voucherId) { String findByIdSQL = "SELECT * FROM vouchers WHERE voucher_id=UUID_TO_BIN(:voucherId)"; diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherRepository.java b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherRepository.java index 8a1bc6c468..c2617690be 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/repository/VoucherRepository.java @@ -1,5 +1,6 @@ package com.programmers.vouchermanagement.voucher.repository; +import java.time.LocalDateTime; import java.util.List; import java.util.Optional; import java.util.UUID; @@ -11,11 +12,12 @@ public interface VoucherRepository { Voucher save(Voucher voucher); List findAll(); List findByType(VoucherType voucherType); + List findByCreatedAt(LocalDateTime startDateTime, LocalDateTime endDateTime); Optional findById(UUID voucherId); List findByCustomerId(UUID customerId); void deleteById(UUID voucherId); void deleteAll(); default boolean existById(UUID voucherId) { return findById(voucherId).isPresent(); - }; + } } diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java b/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java index aadf0982f1..71a4a6b412 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java @@ -1,5 +1,7 @@ package com.programmers.vouchermanagement.voucher.service; +import java.time.LocalDateTime; +import java.time.LocalTime; import java.util.List; import java.util.NoSuchElementException; import java.util.UUID; @@ -11,6 +13,7 @@ import com.programmers.vouchermanagement.voucher.domain.Voucher; import com.programmers.vouchermanagement.voucher.domain.VoucherType; import com.programmers.vouchermanagement.voucher.dto.CreateVoucherRequest; +import com.programmers.vouchermanagement.voucher.dto.SearchCreatedAtRequest; import com.programmers.vouchermanagement.voucher.dto.UpdateVoucherRequest; import com.programmers.vouchermanagement.voucher.dto.VoucherCustomerRequest; import com.programmers.vouchermanagement.voucher.dto.VoucherResponse; @@ -46,6 +49,16 @@ public List findByType(VoucherType voucherType) { .toList(); } + public List findByCreatedAt(SearchCreatedAtRequest request) { + validateDateRange(request); + LocalDateTime startDateTime = request.startDate().atStartOfDay(); + LocalDateTime endDateTime = request.endDate().atTime(LocalTime.MAX); + List vouchers = voucherRepository.findByCreatedAt(startDateTime, endDateTime); + return vouchers.stream() + .map(VoucherResponse::from) + .toList(); + } + public VoucherResponse findById(UUID voucherId) { Voucher voucher = voucherRepository.findById(voucherId) .orElseThrow(() -> new NoSuchElementException("There is no voucher with %s".formatted(voucherId))); @@ -111,4 +124,10 @@ private void validateCustomerIdExisting(UUID customerId) { throw new NoSuchElementException("There is no customer with %s".formatted(customerId)); } } + + private void validateDateRange(SearchCreatedAtRequest request) { + if (request.endDate().isBefore(request.startDate())) { + throw new IllegalArgumentException("The end date should be at least equal to the start date."); + } + } } From cb5e3952800e6e8128dcb0e3c3a9baca974cbe6e Mon Sep 17 00:00:00 2001 From: Jay Date: Thu, 2 Nov 2023 21:23:01 +0900 Subject: [PATCH 14/81] feat: tell the info regarding createdAt from Voucher --- .../vouchermanagement/voucher/domain/Voucher.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/domain/Voucher.java b/src/main/java/com/programmers/vouchermanagement/voucher/domain/Voucher.java index 480ad4a3de..49c5b94543 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/domain/Voucher.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/domain/Voucher.java @@ -55,4 +55,12 @@ public boolean isOwned() { public boolean isSameType(VoucherType voucherType) { return this.voucherType == voucherType; } + + public boolean isCreatedInBetween(LocalDateTime startDateTime, LocalDateTime endDateTime) { + if (createdAt.compareTo(startDateTime) != 1 && createdAt.compareTo(endDateTime) != -1) { + return true; + } + + return false; + } } From f1415253eb9ec24fac0bdab8065be89891697805 Mon Sep 17 00:00:00 2001 From: Jay Date: Thu, 2 Nov 2023 21:23:40 +0900 Subject: [PATCH 15/81] feat: add api endpoint to find vouchers by createdAt --- .../voucher/controller/VoucherRestController.java | 6 ++++++ .../voucher/dto/SearchCreatedAtRequest.java | 6 ++++++ 2 files changed, 12 insertions(+) create mode 100644 src/main/java/com/programmers/vouchermanagement/voucher/dto/SearchCreatedAtRequest.java diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherRestController.java b/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherRestController.java index fb4ffdf158..2bc34227e4 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherRestController.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherRestController.java @@ -12,6 +12,7 @@ import com.programmers.vouchermanagement.voucher.domain.VoucherType; import com.programmers.vouchermanagement.voucher.dto.CreateVoucherRequest; +import com.programmers.vouchermanagement.voucher.dto.SearchCreatedAtRequest; import com.programmers.vouchermanagement.voucher.dto.VoucherResponse; import com.programmers.vouchermanagement.voucher.service.VoucherService; @@ -49,4 +50,9 @@ public List findByType(@PathVariable String typeName) { VoucherType voucherType = VoucherType.findVoucherTypeByName(typeName); return voucherService.findByType(voucherType); } + + @GetMapping("/creation-date") + public List findByCreatedAt(SearchCreatedAtRequest request) { + return voucherService.findByCreatedAt(request); + } } diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/dto/SearchCreatedAtRequest.java b/src/main/java/com/programmers/vouchermanagement/voucher/dto/SearchCreatedAtRequest.java new file mode 100644 index 0000000000..0f2e7b0c8b --- /dev/null +++ b/src/main/java/com/programmers/vouchermanagement/voucher/dto/SearchCreatedAtRequest.java @@ -0,0 +1,6 @@ +package com.programmers.vouchermanagement.voucher.dto; + +import java.time.LocalDate; + +public record SearchCreatedAtRequest(LocalDate startDate, LocalDate endDate) { +} From 0d7498b014d45e90348b14a7a3ba3e5318c531f2 Mon Sep 17 00:00:00 2001 From: Jay Date: Thu, 2 Nov 2023 21:29:37 +0900 Subject: [PATCH 16/81] refactor: improve readability --- .../vouchermanagement/voucher/domain/Voucher.java | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/domain/Voucher.java b/src/main/java/com/programmers/vouchermanagement/voucher/domain/Voucher.java index 49c5b94543..039df751b8 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/domain/Voucher.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/domain/Voucher.java @@ -57,10 +57,6 @@ public boolean isSameType(VoucherType voucherType) { } public boolean isCreatedInBetween(LocalDateTime startDateTime, LocalDateTime endDateTime) { - if (createdAt.compareTo(startDateTime) != 1 && createdAt.compareTo(endDateTime) != -1) { - return true; - } - - return false; + return !createdAt.isBefore(startDateTime) && !createdAt.isAfter(endDateTime); } } From 48bb995b57355c399830dc0b3a348a6db9d22464 Mon Sep 17 00:00:00 2001 From: Jay Date: Thu, 2 Nov 2023 23:19:12 +0900 Subject: [PATCH 17/81] refactor: edit request variables to be close to primitive for validation --- .../consoleapp/io/ConsoleManager.java | 6 ++---- .../voucher/dto/CreateVoucherRequest.java | 7 +++---- .../voucher/service/VoucherService.java | 12 +++++++++++- 3 files changed, 16 insertions(+), 9 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/consoleapp/io/ConsoleManager.java b/src/main/java/com/programmers/vouchermanagement/consoleapp/io/ConsoleManager.java index 6504bcd9c2..2c8f353d70 100644 --- a/src/main/java/com/programmers/vouchermanagement/consoleapp/io/ConsoleManager.java +++ b/src/main/java/com/programmers/vouchermanagement/consoleapp/io/ConsoleManager.java @@ -100,11 +100,9 @@ public CustomerMenu selectCustomerMenu() { } public CreateVoucherRequest instructCreateVoucher() { - String voucherTypeCode = read(VOUCHER_TYPE_INPUT); - VoucherType voucherType = VoucherType.findVoucherTypeByCode(voucherTypeCode); - + String voucherType = read(VOUCHER_TYPE_INPUT); String discountValueInput = read(VOUCHER_DISCOUNT_VALUE_INSTRUCTION); - BigDecimal discountValue = new BigDecimal(discountValueInput); + long discountValue = Long.parseLong(discountValueInput); return new CreateVoucherRequest(discountValue, voucherType); } diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/dto/CreateVoucherRequest.java b/src/main/java/com/programmers/vouchermanagement/voucher/dto/CreateVoucherRequest.java index 69f62dea49..324cbd3e65 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/dto/CreateVoucherRequest.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/dto/CreateVoucherRequest.java @@ -1,8 +1,7 @@ package com.programmers.vouchermanagement.voucher.dto; -import java.math.BigDecimal; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.Positive; -import com.programmers.vouchermanagement.voucher.domain.VoucherType; - -public record CreateVoucherRequest(BigDecimal discountValue, VoucherType voucherType) { +public record CreateVoucherRequest(@Positive long discountValue, @NotBlank String voucherType) { } diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java b/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java index 71a4a6b412..a042bf6c1a 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java @@ -1,5 +1,6 @@ package com.programmers.vouchermanagement.voucher.service; +import java.math.BigDecimal; import java.time.LocalDateTime; import java.time.LocalTime; import java.util.List; @@ -30,7 +31,8 @@ public VoucherService(VoucherRepository voucherRepository, CustomerRepository cu } public VoucherResponse create(CreateVoucherRequest request) { - Voucher voucher = new Voucher(UUID.randomUUID(), request.discountValue(), request.voucherType()); + VoucherType voucherType = findVoucherType(request.voucherType()); + Voucher voucher = new Voucher(UUID.randomUUID(), new BigDecimal(request.discountValue()), voucherType); voucherRepository.save(voucher); return VoucherResponse.from(voucher); } @@ -113,6 +115,14 @@ public List findByCustomerId(UUID customerId) { .toList(); } + private VoucherType findVoucherType(String voucherType) { + try { + return VoucherType.findVoucherTypeByCode(voucherType); + } catch (IllegalArgumentException exception) { + return VoucherType.findVoucherTypeByName(voucherType); + } + } + private void validateVoucherIdExisting(UUID voucherId) { if (!voucherRepository.existById(voucherId)) { throw new NoSuchElementException("There is no voucher with %s".formatted(voucherId)); From 2fd23309d84824b5fbcf2696b5c8ada4cfad6efe Mon Sep 17 00:00:00 2001 From: Jay Date: Thu, 2 Nov 2023 23:19:31 +0900 Subject: [PATCH 18/81] chore: add spring boot validation dependency --- build.gradle | 1 + 1 file changed, 1 insertion(+) diff --git a/build.gradle b/build.gradle index 3a8e7b3ba8..11a30388c5 100644 --- a/build.gradle +++ b/build.gradle @@ -26,6 +26,7 @@ dependencies { testImplementation 'org.testcontainers:mysql:1.19.1' testImplementation 'org.testcontainers:junit-jupiter:1.19.1' implementation 'org.springframework.boot:spring-boot-starter-web:3.1.4' + implementation 'org.springframework.boot:spring-boot-starter-validation:3.1.4' } test { From de91ea59b830c7f72ecdea5358681df6b67e2daf Mon Sep 17 00:00:00 2001 From: Jay Date: Thu, 2 Nov 2023 23:19:51 +0900 Subject: [PATCH 19/81] enhance: validate the create request from the controller --- .../voucher/controller/VoucherRestController.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherRestController.java b/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherRestController.java index 2bc34227e4..2cc7a30213 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherRestController.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherRestController.java @@ -3,6 +3,8 @@ import java.util.List; import java.util.UUID; +import jakarta.validation.Valid; + import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; @@ -26,7 +28,7 @@ public VoucherRestController(VoucherService voucherService) { } @PostMapping - public VoucherResponse create(CreateVoucherRequest createVoucherRequest) { + public VoucherResponse create(@Valid CreateVoucherRequest createVoucherRequest) { return voucherService.create(createVoucherRequest); } From d0cee1dcd99bcc0feefe8e40c8704775af09516a Mon Sep 17 00:00:00 2001 From: Jay Date: Thu, 2 Nov 2023 23:35:36 +0900 Subject: [PATCH 20/81] enhance: add not null validation to SearchCreatedAtRequest --- .../voucher/controller/VoucherRestController.java | 2 +- .../vouchermanagement/voucher/dto/SearchCreatedAtRequest.java | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherRestController.java b/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherRestController.java index 2cc7a30213..5ecc185537 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherRestController.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherRestController.java @@ -54,7 +54,7 @@ public List findByType(@PathVariable String typeName) { } @GetMapping("/creation-date") - public List findByCreatedAt(SearchCreatedAtRequest request) { + public List findByCreatedAt(@Valid SearchCreatedAtRequest request) { return voucherService.findByCreatedAt(request); } } diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/dto/SearchCreatedAtRequest.java b/src/main/java/com/programmers/vouchermanagement/voucher/dto/SearchCreatedAtRequest.java index 0f2e7b0c8b..b2ba5e8883 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/dto/SearchCreatedAtRequest.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/dto/SearchCreatedAtRequest.java @@ -2,5 +2,7 @@ import java.time.LocalDate; -public record SearchCreatedAtRequest(LocalDate startDate, LocalDate endDate) { +import jakarta.validation.constraints.NotNull; + +public record SearchCreatedAtRequest(@NotNull LocalDate startDate, @NotNull LocalDate endDate) { } From d0d6c670c828499b74ebfd117de665b49ccc6950 Mon Sep 17 00:00:00 2001 From: Jay Date: Fri, 3 Nov 2023 13:42:40 +0900 Subject: [PATCH 21/81] chore: add jackson xml dataformat --- build.gradle | 1 + 1 file changed, 1 insertion(+) diff --git a/build.gradle b/build.gradle index 11a30388c5..877ee9095b 100644 --- a/build.gradle +++ b/build.gradle @@ -27,6 +27,7 @@ dependencies { testImplementation 'org.testcontainers:junit-jupiter:1.19.1' implementation 'org.springframework.boot:spring-boot-starter-web:3.1.4' implementation 'org.springframework.boot:spring-boot-starter-validation:3.1.4' + implementation 'com.fasterxml.jackson.dataformat:jackson-dataformat-xml:2.15.2' } test { From c741401aa0df61d4317d647b5d6416204028d73e Mon Sep 17 00:00:00 2001 From: Jay Date: Fri, 3 Nov 2023 13:43:14 +0900 Subject: [PATCH 22/81] enhance: produce responses in both json and xml --- .../voucher/controller/VoucherRestController.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherRestController.java b/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherRestController.java index 5ecc185537..03d5a26030 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherRestController.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherRestController.java @@ -5,6 +5,7 @@ import jakarta.validation.Valid; +import org.springframework.http.MediaType; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; @@ -19,7 +20,7 @@ import com.programmers.vouchermanagement.voucher.service.VoucherService; @RestController -@RequestMapping("/api/v1/vouchers") +@RequestMapping(value = "/api/v1/vouchers", produces = {MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE}) public class VoucherRestController { private final VoucherService voucherService; From e45343f97aba1d25178669fd66b77e6e05bec0a1 Mon Sep 17 00:00:00 2001 From: Jay Date: Sat, 4 Nov 2023 11:27:12 +0900 Subject: [PATCH 23/81] feat: add controller advice to handle exceptions --- .../advice/ControllerAdvice.java | 36 +++++++++++++++++++ .../advice/ExceptionMessage.java | 13 +++++++ 2 files changed, 49 insertions(+) create mode 100644 src/main/java/com/programmers/vouchermanagement/advice/ControllerAdvice.java create mode 100644 src/main/java/com/programmers/vouchermanagement/advice/ExceptionMessage.java diff --git a/src/main/java/com/programmers/vouchermanagement/advice/ControllerAdvice.java b/src/main/java/com/programmers/vouchermanagement/advice/ControllerAdvice.java new file mode 100644 index 0000000000..5bbaeced21 --- /dev/null +++ b/src/main/java/com/programmers/vouchermanagement/advice/ControllerAdvice.java @@ -0,0 +1,36 @@ +package com.programmers.vouchermanagement.advice; + +import java.util.NoSuchElementException; + +import org.springframework.http.HttpStatus; +import org.springframework.validation.BindingResult; +import org.springframework.validation.FieldError; +import org.springframework.web.bind.MethodArgumentNotValidException; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.bind.annotation.RestControllerAdvice; + +@RestControllerAdvice +public class ControllerAdvice { + + @ExceptionHandler(MethodArgumentNotValidException.class) + @ResponseStatus(HttpStatus.BAD_REQUEST) + public ExceptionMessage handleInvalidMethodArgumentException(BindingResult bindingResult) { + FieldError error = bindingResult.getFieldErrors() + .get(0); + String message = error.getField() + " exception - " + error.getDefaultMessage(); + return new ExceptionMessage(message); + } + + @ExceptionHandler(IllegalArgumentException.class) + @ResponseStatus(HttpStatus.BAD_REQUEST) + public ExceptionMessage handleIllegalArgumentException(IllegalArgumentException exception) { + return new ExceptionMessage(exception.getMessage()); + } + + @ExceptionHandler(NoSuchElementException.class) + @ResponseStatus(HttpStatus.NOT_FOUND) + public ExceptionMessage handleNoSuchElementException(NoSuchElementException exception) { + return new ExceptionMessage(exception.getMessage()); + } +} diff --git a/src/main/java/com/programmers/vouchermanagement/advice/ExceptionMessage.java b/src/main/java/com/programmers/vouchermanagement/advice/ExceptionMessage.java new file mode 100644 index 0000000000..4bd9dba6fc --- /dev/null +++ b/src/main/java/com/programmers/vouchermanagement/advice/ExceptionMessage.java @@ -0,0 +1,13 @@ +package com.programmers.vouchermanagement.advice; + +public class ExceptionMessage { + private final String message; + + public ExceptionMessage(String message) { + this.message = message; + } + + public String getMessage() { + return message; + } +} From 8ab774cec4c811b7c3444501bcab77b5ce65b27a Mon Sep 17 00:00:00 2001 From: Jay Date: Sat, 4 Nov 2023 11:29:02 +0900 Subject: [PATCH 24/81] enhance: elaborate the validation messages --- .../voucher/controller/VoucherController.java | 6 +++--- .../voucher/dto/CreateVoucherRequest.java | 5 ++++- .../voucher/dto/SearchCreatedAtRequest.java | 7 +++++-- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherController.java b/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherController.java index 4e9f4fed75..7c467f8900 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherController.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherController.java @@ -1,14 +1,14 @@ package com.programmers.vouchermanagement.voucher.controller; -import org.springframework.stereotype.Controller; - import java.util.List; import java.util.UUID; +import org.springframework.stereotype.Controller; + import com.programmers.vouchermanagement.consoleapp.io.ConsoleManager; -import com.programmers.vouchermanagement.voucher.dto.VoucherCustomerRequest; import com.programmers.vouchermanagement.voucher.dto.CreateVoucherRequest; import com.programmers.vouchermanagement.voucher.dto.UpdateVoucherRequest; +import com.programmers.vouchermanagement.voucher.dto.VoucherCustomerRequest; import com.programmers.vouchermanagement.voucher.dto.VoucherResponse; import com.programmers.vouchermanagement.voucher.service.VoucherService; diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/dto/CreateVoucherRequest.java b/src/main/java/com/programmers/vouchermanagement/voucher/dto/CreateVoucherRequest.java index 324cbd3e65..be3d77b9fb 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/dto/CreateVoucherRequest.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/dto/CreateVoucherRequest.java @@ -3,5 +3,8 @@ import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.Positive; -public record CreateVoucherRequest(@Positive long discountValue, @NotBlank String voucherType) { +public record CreateVoucherRequest( + @Positive(message = "Discount value must be greater than 0.") long discountValue, + @NotBlank(message = "Voucher type cannot be blank.") String voucherType +) { } diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/dto/SearchCreatedAtRequest.java b/src/main/java/com/programmers/vouchermanagement/voucher/dto/SearchCreatedAtRequest.java index b2ba5e8883..849f2dc8ed 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/dto/SearchCreatedAtRequest.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/dto/SearchCreatedAtRequest.java @@ -2,7 +2,10 @@ import java.time.LocalDate; -import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.NotBlank; -public record SearchCreatedAtRequest(@NotNull LocalDate startDate, @NotNull LocalDate endDate) { +public record SearchCreatedAtRequest( + @NotBlank(message = "Start-date cannot be blank.") LocalDate startDate, + @NotBlank(message = "End-date cannot be blank.") LocalDate endDate +) { } From a1f83b4def513fd5f2990bcb3da7fa96482e3d9f Mon Sep 17 00:00:00 2001 From: Jay Date: Sat, 4 Nov 2023 11:29:33 +0900 Subject: [PATCH 25/81] enhance: attach response status --- .../voucher/controller/VoucherRestController.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherRestController.java b/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherRestController.java index 03d5a26030..170442262e 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherRestController.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherRestController.java @@ -5,12 +5,14 @@ import jakarta.validation.Valid; +import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; 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.ResponseStatus; import org.springframework.web.bind.annotation.RestController; import com.programmers.vouchermanagement.voucher.domain.VoucherType; @@ -29,32 +31,38 @@ public VoucherRestController(VoucherService voucherService) { } @PostMapping + @ResponseStatus(HttpStatus.CREATED) public VoucherResponse create(@Valid CreateVoucherRequest createVoucherRequest) { return voucherService.create(createVoucherRequest); } @GetMapping + @ResponseStatus(HttpStatus.OK) public List readAllVouchers() { return voucherService.readAllVouchers(); } @GetMapping("/{voucherId}") + @ResponseStatus(HttpStatus.OK) public VoucherResponse findById(@PathVariable UUID voucherId) { return voucherService.findById(voucherId); } @DeleteMapping("/{voucherId}") + @ResponseStatus(HttpStatus.ACCEPTED) public void deleteById(@PathVariable UUID voucherId) { voucherService.deleteById(voucherId); } @GetMapping("/type/{typeName}") + @ResponseStatus(HttpStatus.OK) public List findByType(@PathVariable String typeName) { VoucherType voucherType = VoucherType.findVoucherTypeByName(typeName); return voucherService.findByType(voucherType); } @GetMapping("/creation-date") + @ResponseStatus(HttpStatus.OK) public List findByCreatedAt(@Valid SearchCreatedAtRequest request) { return voucherService.findByCreatedAt(request); } From 29e4faed04017bc841365f577b983ea000a99ceb Mon Sep 17 00:00:00 2001 From: Jay Date: Sat, 4 Nov 2023 12:59:42 +0900 Subject: [PATCH 26/81] fix: convert LocalDateTime to String --- .../voucher/repository/FileVoucherRepository.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/repository/FileVoucherRepository.java b/src/main/java/com/programmers/vouchermanagement/voucher/repository/FileVoucherRepository.java index 9ccbf3404a..25dc4770be 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/repository/FileVoucherRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/repository/FileVoucherRepository.java @@ -48,7 +48,7 @@ public class FileVoucherRepository implements VoucherRepository { private final Function> voucherToObject = (voucher) -> { HashMap voucherObject = new HashMap<>(); voucherObject.put(VOUCHER_ID_KEY, voucher.getVoucherId().toString()); - voucherObject.put(VOUCHER_CREATED_AT_KEY, voucher.getCreatedAt()); + voucherObject.put(VOUCHER_CREATED_AT_KEY, voucher.getCreatedAt().toString()); voucherObject.put(DISCOUNT_VALUE_KEY, voucher.getDiscountValue().toString()); voucherObject.put(VOUCHER_TYPE_KEY, voucher.getVoucherType().name()); voucherObject.put(CUSTOMER_ID_KEY, voucher.getCustomerId()); From fbf474c1b9123b22fa2fad0d5bdc8e23ac650e83 Mon Sep 17 00:00:00 2001 From: Jay Date: Sat, 4 Nov 2023 13:00:38 +0900 Subject: [PATCH 27/81] fix: apply the addition of createdAt --- .../programmers/vouchermanagement/util/Formatter.java | 2 +- .../consoleapp/menu/MenuHandlerTest.java | 10 ++++++---- .../voucher/repository/JdbcVoucherRepositoryTest.java | 4 ++-- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/util/Formatter.java b/src/main/java/com/programmers/vouchermanagement/util/Formatter.java index dd0f2b0689..b6b9533b0c 100644 --- a/src/main/java/com/programmers/vouchermanagement/util/Formatter.java +++ b/src/main/java/com/programmers/vouchermanagement/util/Formatter.java @@ -38,7 +38,7 @@ public static String formatVoucher(VoucherResponse voucherResponse) { return VOUCHER_PRESENTATION_FORMAT .formatted(voucherResponse.voucherId(), voucherResponse.createdAt(), - voucherResponse.voucherType(), + voucherResponse.voucherType().displayTypeName(), voucherResponse.discountValue() + markPercentage(voucherResponse.voucherType())); } diff --git a/src/test/java/com/programmers/vouchermanagement/consoleapp/menu/MenuHandlerTest.java b/src/test/java/com/programmers/vouchermanagement/consoleapp/menu/MenuHandlerTest.java index fa991e1c2d..a536c74de5 100644 --- a/src/test/java/com/programmers/vouchermanagement/consoleapp/menu/MenuHandlerTest.java +++ b/src/test/java/com/programmers/vouchermanagement/consoleapp/menu/MenuHandlerTest.java @@ -13,6 +13,7 @@ import org.springframework.test.context.ActiveProfiles; import com.programmers.vouchermanagement.consoleapp.io.ConsoleManager; +import com.programmers.vouchermanagement.customer.repository.CustomerRepository; import com.programmers.vouchermanagement.voucher.repository.VoucherRepository; @SpringBootTest @@ -21,6 +22,8 @@ class MenuHandlerTest { @Autowired VoucherRepository voucherRepository; @Autowired + CustomerRepository customerRepository; + @Autowired MockTextTerminal textTerminal; @Autowired ConsoleManager consoleManager; @@ -108,17 +111,16 @@ void testExecuteCustomerMenu_IncorrectMenu() { void testExecuteCustomerMenu_CorrectMenu() { //given textTerminal.getInputs() - .add("6"); + .addAll(List.of("1", "tester")); //when menuHandler.handleMenu(Menu.CUSTOMER); String output = textTerminal.getOutput(); //then - assertThat(output, containsString("Customer ID :")); - assertThat(output, containsString("Customer Name :")); + assertThat(output, containsString("successfully saved")); //clean - voucherRepository.deleteAll(); + customerRepository.deleteAll(); } } diff --git a/src/test/java/com/programmers/vouchermanagement/voucher/repository/JdbcVoucherRepositoryTest.java b/src/test/java/com/programmers/vouchermanagement/voucher/repository/JdbcVoucherRepositoryTest.java index be40ab46ce..8d4e92339a 100644 --- a/src/test/java/com/programmers/vouchermanagement/voucher/repository/JdbcVoucherRepositoryTest.java +++ b/src/test/java/com/programmers/vouchermanagement/voucher/repository/JdbcVoucherRepositoryTest.java @@ -114,7 +114,7 @@ void testFindVoucherByIdSuccessful_ReturnList() { //then assertThat(foundVoucher.isEmpty(), is(false)); - assertThat(foundVoucher.get(), samePropertyValuesAs(voucher)); + assertThat(foundVoucher.get().getVoucherId(), is(voucher.getVoucherId())); } @Test @@ -145,7 +145,7 @@ void testVoucherUpdateSuccessful() { Voucher newlyFoundVoucher = voucherRepository.findById(foundVoucher.getVoucherId()).get(); //then - assertThat(newlyFoundVoucher, samePropertyValuesAs(updatedVoucher)); + assertThat(newlyFoundVoucher.getDiscountValue(), is(updatedVoucher.getDiscountValue())); } @Test From 8b6dce134f9e2591e1d0c789dfff575fd5007beb Mon Sep 17 00:00:00 2001 From: Jay Date: Sat, 4 Nov 2023 13:01:02 +0900 Subject: [PATCH 28/81] fix: apply the change of parameters of CreateRequest --- .../voucher/controller/VoucherControllerTest.java | 10 +++++----- .../voucher/service/VoucherServiceTest.java | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/test/java/com/programmers/vouchermanagement/voucher/controller/VoucherControllerTest.java b/src/test/java/com/programmers/vouchermanagement/voucher/controller/VoucherControllerTest.java index ef2de3ee2d..3b566ca4b9 100644 --- a/src/test/java/com/programmers/vouchermanagement/voucher/controller/VoucherControllerTest.java +++ b/src/test/java/com/programmers/vouchermanagement/voucher/controller/VoucherControllerTest.java @@ -49,7 +49,7 @@ void setUp() { @DisplayName("바우처 생성을 성공하고 바우처 생성 성공 뷰를 출력한다.") void testCreateVoucher_ViewShowingCreatedVoucher() { //given - CreateVoucherRequest request = new CreateVoucherRequest(new BigDecimal(10000), VoucherType.FIXED); + CreateVoucherRequest request = new CreateVoucherRequest(10000, "Fixed"); //when voucherController.create(request); @@ -83,7 +83,7 @@ void testReadAllVouchers_NoVoucher() { @DisplayName("저장된 바우처들의 전체 조회를 성공하고 바우처 정보를 보여주는 뷰를 출력한다.") void testReadAllVouchers_ViewShowingVouchers() { //given - CreateVoucherRequest request = new CreateVoucherRequest(new BigDecimal(10000), VoucherType.FIXED); + CreateVoucherRequest request = new CreateVoucherRequest(10000, "Fixed"); voucherController.create(request); //when @@ -118,7 +118,7 @@ void testFindVoucherById_ViewShowingFoundVoucher() { @DisplayName("바우처 정보 업데이트 성공 시 성공 문구를 담은 뷰를 출력한다.") void testUpdateVoucher_ViewShowingUpdatedVoucher() { //given - CreateVoucherRequest createRequest = new CreateVoucherRequest(new BigDecimal(10000), VoucherType.FIXED); + CreateVoucherRequest createRequest = new CreateVoucherRequest(10000, "Fixed"); VoucherResponse voucher = voucherService.create(createRequest); UpdateVoucherRequest updateRequest = new UpdateVoucherRequest(voucher.voucherId(), new BigDecimal(20000), VoucherType.FIXED); @@ -135,7 +135,7 @@ void testUpdateVoucher_ViewShowingUpdatedVoucher() { @DisplayName("바우처의 삭제 성공 후 성공 문구를 담은 뷰를 출력한다.") void testDeleteVoucherById_SuccessfullyDeleted() { //given - CreateVoucherRequest createRequest = new CreateVoucherRequest(new BigDecimal(10000), VoucherType.FIXED); + CreateVoucherRequest createRequest = new CreateVoucherRequest(10000, "Fixed"); VoucherResponse voucher = voucherService.create(createRequest); //when @@ -150,7 +150,7 @@ void testDeleteVoucherById_SuccessfullyDeleted() { @DisplayName("바우처 할당 성공 시 성공 문구를 담은 뷰를 출력한다.") void testGrantVoucherToCustomer_SuccessfullyGranted() { //given - CreateVoucherRequest createRequest = new CreateVoucherRequest(new BigDecimal(10000), VoucherType.FIXED); + CreateVoucherRequest createRequest = new CreateVoucherRequest(10000, "Fixed"); VoucherResponse voucher = voucherService.create(createRequest); Customer customer = new Customer(UUID.randomUUID(), "test-customer"); customerRepository.save(customer); diff --git a/src/test/java/com/programmers/vouchermanagement/voucher/service/VoucherServiceTest.java b/src/test/java/com/programmers/vouchermanagement/voucher/service/VoucherServiceTest.java index f8f7bbd21f..06066e4a69 100644 --- a/src/test/java/com/programmers/vouchermanagement/voucher/service/VoucherServiceTest.java +++ b/src/test/java/com/programmers/vouchermanagement/voucher/service/VoucherServiceTest.java @@ -53,7 +53,7 @@ void setUp() { @DisplayName("고정 금액 바우처 생성에 성공한다.") void testFixedVoucherCreationSuccessful() { //given - CreateVoucherRequest request = new CreateVoucherRequest(new BigDecimal("100"), VoucherType.FIXED); + CreateVoucherRequest request = new CreateVoucherRequest(10000, "Fixed"); //when VoucherResponse voucher = voucherService.create(request); @@ -68,7 +68,7 @@ void testFixedVoucherCreationSuccessful() { @DisplayName("유효하지 않은 할인 값의 고정 금액 바우처 생성에 실패한다.") void testFixedVoucherCreationFailed_InvalidAmount() { //given - CreateVoucherRequest request = new CreateVoucherRequest(new BigDecimal("0"), VoucherType.FIXED); + CreateVoucherRequest request = new CreateVoucherRequest(0, "1"); //when assertThatThrownBy(() -> voucherService.create(request)) @@ -84,7 +84,7 @@ void testFixedVoucherCreationFailed_InvalidAmount() { @DisplayName("퍼센트 할인 바우처 생성에 성공한다.") void textPercentVoucherCreationSuccessful() { //given - CreateVoucherRequest request = new CreateVoucherRequest(new BigDecimal("50"), VoucherType.PERCENT); + CreateVoucherRequest request = new CreateVoucherRequest(50, "Percent"); //when VoucherResponse voucher = voucherService.create(request); @@ -99,8 +99,8 @@ void textPercentVoucherCreationSuccessful() { @DisplayName("유효하지 않은 할인율의 퍼센트 할인 바우처 생성에 실패한다.") void testPercentVoucherCreationFailed_InvalidPercent() { //given - CreateVoucherRequest firstRequest = new CreateVoucherRequest(new BigDecimal("0"), VoucherType.PERCENT); - CreateVoucherRequest secondRequest = new CreateVoucherRequest(new BigDecimal("100.1"), VoucherType.PERCENT); + CreateVoucherRequest firstRequest = new CreateVoucherRequest(0, "Percent"); + CreateVoucherRequest secondRequest = new CreateVoucherRequest(101, "Percent"); //when assertThatThrownBy(() -> voucherService.create(firstRequest)) From f8e9c7d18ebeeb0048ec085ecc3ee898b97f4755 Mon Sep 17 00:00:00 2001 From: Jay Date: Sat, 4 Nov 2023 13:07:23 +0900 Subject: [PATCH 29/81] chore: add thymeleaf dependency --- build.gradle | 1 + 1 file changed, 1 insertion(+) diff --git a/build.gradle b/build.gradle index 877ee9095b..a6a7675bc0 100644 --- a/build.gradle +++ b/build.gradle @@ -28,6 +28,7 @@ dependencies { implementation 'org.springframework.boot:spring-boot-starter-web:3.1.4' implementation 'org.springframework.boot:spring-boot-starter-validation:3.1.4' implementation 'com.fasterxml.jackson.dataformat:jackson-dataformat-xml:2.15.2' + implementation 'org.springframework.boot:spring-boot-starter-thymeleaf:3.1.4' } test { From ef8f2d5f0d4ef83df8afe60789f4a7fb0337353b Mon Sep 17 00:00:00 2001 From: Jay Date: Sat, 4 Nov 2023 19:38:39 +0900 Subject: [PATCH 30/81] feat: implement read all vouchers controller for web --- .../controller/VoucherAdminController.java | 30 ++++++++++++++ .../templates/vouchers/vouchers.html | 41 +++++++++++++++++++ 2 files changed, 71 insertions(+) create mode 100644 src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherAdminController.java create mode 100644 src/main/resources/templates/vouchers/vouchers.html diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherAdminController.java b/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherAdminController.java new file mode 100644 index 0000000000..f60ee0a896 --- /dev/null +++ b/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherAdminController.java @@ -0,0 +1,30 @@ +package com.programmers.vouchermanagement.voucher.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.RequestMapping; + +import com.programmers.vouchermanagement.voucher.dto.VoucherResponse; +import com.programmers.vouchermanagement.voucher.service.VoucherService; + +@Controller +@RequestMapping("/vouchers") +public class VoucherAdminController { + private final VoucherService voucherService; + + public VoucherAdminController(VoucherService voucherService) { + this.voucherService = voucherService; + } + + @GetMapping + public String readAllVouchers(Model model) { + List vouchers = voucherService.readAllVouchers(); + model.addAttribute("vouchers", vouchers); + return "vouchers/vouchers"; + } +} diff --git a/src/main/resources/templates/vouchers/vouchers.html b/src/main/resources/templates/vouchers/vouchers.html new file mode 100644 index 0000000000..3896fa2149 --- /dev/null +++ b/src/main/resources/templates/vouchers/vouchers.html @@ -0,0 +1,41 @@ + + + + + + + Voucher Management Admin - Vouchers + + +
+
+

All Vouchers

+
+
+
+
+ Voucher ID + Creation Datetime + Discount Value + Voucher Type +
+ +
+
+
+ + + + +
+ +
+
+
+ + From 5e8428473f0262303fe26163858ee59921ff80bd Mon Sep 17 00:00:00 2001 From: Jay Date: Sat, 4 Nov 2023 19:38:54 +0900 Subject: [PATCH 31/81] feat: implement vouchers view --- .../resources/templates/vouchers/voucher.html | 52 +++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 src/main/resources/templates/vouchers/voucher.html diff --git a/src/main/resources/templates/vouchers/voucher.html b/src/main/resources/templates/vouchers/voucher.html new file mode 100644 index 0000000000..63346dbdaf --- /dev/null +++ b/src/main/resources/templates/vouchers/voucher.html @@ -0,0 +1,52 @@ + + + + + + + Voucher Management Admin - Voucher Detail + + +
+
+

Voucher Detail

+
+
+
+
+ Voucher ID : +
+
+ Creation Datetime : +
+
+ + +
+
+ + +
+
+ Current Voucher Type : Discount Voucher +
+
+ +
+
+
+ + From f6132aa4f50de3e824689466e34dd21f967cdb06 Mon Sep 17 00:00:00 2001 From: Jay Date: Sat, 4 Nov 2023 19:39:16 +0900 Subject: [PATCH 32/81] feat: implement find voucher by id controller for web --- .../voucher/controller/VoucherAdminController.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherAdminController.java b/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherAdminController.java index f60ee0a896..671e15f9ed 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherAdminController.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherAdminController.java @@ -27,4 +27,11 @@ public String readAllVouchers(Model model) { model.addAttribute("vouchers", vouchers); return "vouchers/vouchers"; } + + @GetMapping("/{voucherId}") + public String findById(@PathVariable UUID voucherId, Model model) { + VoucherResponse voucher = voucherService.findById(voucherId); + model.addAttribute("voucher", voucher); + return "vouchers/voucher"; + } } From 1b70792ed57128ad80a3d6058f14ecf7b8331ca2 Mon Sep 17 00:00:00 2001 From: Jay Date: Sat, 4 Nov 2023 19:41:01 +0900 Subject: [PATCH 33/81] feat: implement home page --- src/main/resources/templates/index.html | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 src/main/resources/templates/index.html diff --git a/src/main/resources/templates/index.html b/src/main/resources/templates/index.html new file mode 100644 index 0000000000..23e6619b3d --- /dev/null +++ b/src/main/resources/templates/index.html @@ -0,0 +1,25 @@ + + + + + + + Voucher Management Admin + + +
+

Voucher Management Admin

+
+
+

Select Service Menu

+
+ + + From c06ba66272eb535553ad837d92f57d448b6f0393 Mon Sep 17 00:00:00 2001 From: Jay Date: Sat, 4 Nov 2023 20:03:23 +0900 Subject: [PATCH 34/81] refactor: retrieve primitive types for parameters of dto --- .../consoleapp/io/ConsoleManager.java | 6 ++---- .../voucher/dto/UpdateVoucherRequest.java | 5 +---- .../voucher/service/VoucherService.java | 13 +++---------- .../voucher/controller/VoucherControllerTest.java | 2 +- .../voucher/service/VoucherServiceTest.java | 6 +++--- 5 files changed, 10 insertions(+), 22 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/consoleapp/io/ConsoleManager.java b/src/main/java/com/programmers/vouchermanagement/consoleapp/io/ConsoleManager.java index 2c8f353d70..bbf1c5025a 100644 --- a/src/main/java/com/programmers/vouchermanagement/consoleapp/io/ConsoleManager.java +++ b/src/main/java/com/programmers/vouchermanagement/consoleapp/io/ConsoleManager.java @@ -110,12 +110,10 @@ public UpdateVoucherRequest instructUpdateVoucher() { String voucherIdInput = read(ID_INPUT.formatted(CONTENT_VOUCHER)); UUID voucherId = UUID.fromString(voucherIdInput); - String discountValueInput = read(VOUCHER_DISCOUNT_VALUE_INSTRUCTION); - BigDecimal discountValue = new BigDecimal(discountValueInput); + String discountValue = read(VOUCHER_DISCOUNT_VALUE_INSTRUCTION); String voucherTypeCode = read(VOUCHER_TYPE_INPUT); - VoucherType voucherType = VoucherType.findVoucherTypeByCode(voucherTypeCode); - return new UpdateVoucherRequest(voucherId, discountValue, voucherType); + return new UpdateVoucherRequest(voucherId, Long.parseLong(discountValue), voucherTypeCode); } public String instructCreateCustomer() { diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/dto/UpdateVoucherRequest.java b/src/main/java/com/programmers/vouchermanagement/voucher/dto/UpdateVoucherRequest.java index fd4c133792..156c10f28f 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/dto/UpdateVoucherRequest.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/dto/UpdateVoucherRequest.java @@ -1,9 +1,6 @@ package com.programmers.vouchermanagement.voucher.dto; -import java.math.BigDecimal; import java.util.UUID; -import com.programmers.vouchermanagement.voucher.domain.VoucherType; - -public record UpdateVoucherRequest(UUID voucherId, BigDecimal discountValue, VoucherType voucherType) { +public record UpdateVoucherRequest(UUID voucherId, long discountValue, String voucherType) { } diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java b/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java index a042bf6c1a..64979f6746 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java @@ -31,7 +31,7 @@ public VoucherService(VoucherRepository voucherRepository, CustomerRepository cu } public VoucherResponse create(CreateVoucherRequest request) { - VoucherType voucherType = findVoucherType(request.voucherType()); + VoucherType voucherType = VoucherType.findVoucherType(request.voucherType()); Voucher voucher = new Voucher(UUID.randomUUID(), new BigDecimal(request.discountValue()), voucherType); voucherRepository.save(voucher); return VoucherResponse.from(voucher); @@ -69,7 +69,8 @@ public VoucherResponse findById(UUID voucherId) { public VoucherResponse update(UpdateVoucherRequest request) { validateVoucherIdExisting(request.voucherId()); - Voucher voucher = new Voucher(request.voucherId(), request.discountValue(), request.voucherType()); + VoucherType voucherType = VoucherType.findVoucherType(request.voucherType()); + Voucher voucher = new Voucher(request.voucherId(), new BigDecimal(request.discountValue()), voucherType); Voucher updatedVoucher = voucherRepository.save(voucher); return VoucherResponse.from(updatedVoucher); } @@ -115,14 +116,6 @@ public List findByCustomerId(UUID customerId) { .toList(); } - private VoucherType findVoucherType(String voucherType) { - try { - return VoucherType.findVoucherTypeByCode(voucherType); - } catch (IllegalArgumentException exception) { - return VoucherType.findVoucherTypeByName(voucherType); - } - } - private void validateVoucherIdExisting(UUID voucherId) { if (!voucherRepository.existById(voucherId)) { throw new NoSuchElementException("There is no voucher with %s".formatted(voucherId)); diff --git a/src/test/java/com/programmers/vouchermanagement/voucher/controller/VoucherControllerTest.java b/src/test/java/com/programmers/vouchermanagement/voucher/controller/VoucherControllerTest.java index 3b566ca4b9..0f7b87ae3c 100644 --- a/src/test/java/com/programmers/vouchermanagement/voucher/controller/VoucherControllerTest.java +++ b/src/test/java/com/programmers/vouchermanagement/voucher/controller/VoucherControllerTest.java @@ -120,7 +120,7 @@ void testUpdateVoucher_ViewShowingUpdatedVoucher() { //given CreateVoucherRequest createRequest = new CreateVoucherRequest(10000, "Fixed"); VoucherResponse voucher = voucherService.create(createRequest); - UpdateVoucherRequest updateRequest = new UpdateVoucherRequest(voucher.voucherId(), new BigDecimal(20000), VoucherType.FIXED); + UpdateVoucherRequest updateRequest = new UpdateVoucherRequest(voucher.voucherId(), 20000, "Fixed"); //when voucherController.update(updateRequest); diff --git a/src/test/java/com/programmers/vouchermanagement/voucher/service/VoucherServiceTest.java b/src/test/java/com/programmers/vouchermanagement/voucher/service/VoucherServiceTest.java index 06066e4a69..eb281d3ad5 100644 --- a/src/test/java/com/programmers/vouchermanagement/voucher/service/VoucherServiceTest.java +++ b/src/test/java/com/programmers/vouchermanagement/voucher/service/VoucherServiceTest.java @@ -171,7 +171,7 @@ void testFindVoucherByIdSuccessful() { @DisplayName("존재하지 않는 바우처의 정보 수정을 실패한다.") void testUpdateVoucherFailed_NonExistentVoucher() { //given - UpdateVoucherRequest request = new UpdateVoucherRequest(UUID.randomUUID(), new BigDecimal(1000), VoucherType.FIXED); + UpdateVoucherRequest request = new UpdateVoucherRequest(UUID.randomUUID(), 1000, "Fixed"); //when assertThatThrownBy(() -> voucherService.update(request)) @@ -189,7 +189,7 @@ void testUpdateVoucherFailed_InvalidDiscountValue() { //given Voucher voucher = new Voucher(UUID.randomUUID(), new BigDecimal(10000), VoucherType.FIXED); voucherRepository.save(voucher); - UpdateVoucherRequest request = new UpdateVoucherRequest(voucher.getVoucherId(), BigDecimal.ZERO, VoucherType.FIXED); + UpdateVoucherRequest request = new UpdateVoucherRequest(voucher.getVoucherId(), 0, "Fixed"); //when assertThatThrownBy(() -> voucherService.update(request)) @@ -208,7 +208,7 @@ void testUpdateVoucherSuccessful() { //given Voucher voucher = new Voucher(UUID.randomUUID(), new BigDecimal(10000), VoucherType.FIXED); voucherRepository.save(voucher); - UpdateVoucherRequest request = new UpdateVoucherRequest(voucher.getVoucherId(), BigDecimal.TEN, VoucherType.PERCENT); + UpdateVoucherRequest request = new UpdateVoucherRequest(voucher.getVoucherId(), 10, "Percent"); //when VoucherResponse voucherResponse = voucherService.update(request); From 5ff79ebde5e70f024cc624e76d1261ad538e5e49 Mon Sep 17 00:00:00 2001 From: Jay Date: Sat, 4 Nov 2023 20:05:23 +0900 Subject: [PATCH 35/81] refactor: find voucher type regardless of the string form --- .../consoleapp/io/ConsoleManager.java | 2 -- .../voucher/controller/VoucherRestController.java | 2 +- .../voucher/domain/VoucherType.java | 12 ++++++++++-- .../voucher/repository/FileVoucherRepository.java | 2 +- .../voucher/repository/JdbcVoucherRepository.java | 2 +- .../voucher/domain/VoucherTypeTest.java | 10 +++++----- 6 files changed, 18 insertions(+), 12 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/consoleapp/io/ConsoleManager.java b/src/main/java/com/programmers/vouchermanagement/consoleapp/io/ConsoleManager.java index bbf1c5025a..3b3c7810a3 100644 --- a/src/main/java/com/programmers/vouchermanagement/consoleapp/io/ConsoleManager.java +++ b/src/main/java/com/programmers/vouchermanagement/consoleapp/io/ConsoleManager.java @@ -1,6 +1,5 @@ package com.programmers.vouchermanagement.consoleapp.io; -import java.math.BigDecimal; import java.util.List; import java.util.UUID; @@ -14,7 +13,6 @@ import com.programmers.vouchermanagement.customer.dto.CustomerResponse; import com.programmers.vouchermanagement.customer.dto.UpdateCustomerRequest; import com.programmers.vouchermanagement.util.Formatter; -import com.programmers.vouchermanagement.voucher.domain.VoucherType; import com.programmers.vouchermanagement.voucher.dto.CreateVoucherRequest; import com.programmers.vouchermanagement.voucher.dto.UpdateVoucherRequest; import com.programmers.vouchermanagement.voucher.dto.VoucherCustomerRequest; diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherRestController.java b/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherRestController.java index 170442262e..3ab2fab3f3 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherRestController.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherRestController.java @@ -57,7 +57,7 @@ public void deleteById(@PathVariable UUID voucherId) { @GetMapping("/type/{typeName}") @ResponseStatus(HttpStatus.OK) public List findByType(@PathVariable String typeName) { - VoucherType voucherType = VoucherType.findVoucherTypeByName(typeName); + VoucherType voucherType = VoucherType.findVoucherType(typeName); return voucherService.findByType(voucherType); } diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/domain/VoucherType.java b/src/main/java/com/programmers/vouchermanagement/voucher/domain/VoucherType.java index 44ceb493f1..62bc018c2b 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/domain/VoucherType.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/domain/VoucherType.java @@ -34,7 +34,15 @@ public enum VoucherType { this.validator = validator; } - public static VoucherType findVoucherTypeByName(String input) { + public static VoucherType findVoucherType(String input) { + try { + return VoucherType.findVoucherTypeByCode(input); + } catch (IllegalArgumentException exception) { + return VoucherType.findVoucherTypeByName(input); + } + } + + private static VoucherType findVoucherTypeByName(String input) { return Arrays.stream(VoucherType.values()) .filter(menu -> menu.isMatchingName(input)) .findFirst() @@ -44,7 +52,7 @@ public static VoucherType findVoucherTypeByName(String input) { }); } - public static VoucherType findVoucherTypeByCode(String input) { + private static VoucherType findVoucherTypeByCode(String input) { return Arrays.stream(VoucherType.values()) .filter(menu -> menu.isMatchingCode(input)) .findFirst() diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/repository/FileVoucherRepository.java b/src/main/java/com/programmers/vouchermanagement/voucher/repository/FileVoucherRepository.java index 25dc4770be..99e2e5f56f 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/repository/FileVoucherRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/repository/FileVoucherRepository.java @@ -40,7 +40,7 @@ public class FileVoucherRepository implements VoucherRepository { LocalDateTime createdAt = LocalDateTime.parse(String.valueOf(voucherObject.get(VOUCHER_CREATED_AT_KEY))); BigDecimal discountValue = new BigDecimal(String.valueOf(voucherObject.get(DISCOUNT_VALUE_KEY))); String voucherTypeName = String.valueOf(voucherObject.get(VOUCHER_TYPE_KEY)); - VoucherType voucherType = VoucherType.findVoucherTypeByName(voucherTypeName); + VoucherType voucherType = VoucherType.findVoucherType(voucherTypeName); String customerIdString = String.valueOf(voucherObject.get(CUSTOMER_ID_KEY)); UUID customerId = customerIdString.equals("null") ? null : UUID.fromString(customerIdString); return new Voucher(voucherId, createdAt, discountValue, voucherType, customerId); diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/repository/JdbcVoucherRepository.java b/src/main/java/com/programmers/vouchermanagement/voucher/repository/JdbcVoucherRepository.java index 5231aa8a92..612f3d7baa 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/repository/JdbcVoucherRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/repository/JdbcVoucherRepository.java @@ -127,7 +127,7 @@ private static Voucher mapToVoucher(ResultSet resultSet) throws SQLException { final LocalDateTime createdAt = resultSet.getTimestamp("created_at").toLocalDateTime(); final BigDecimal discountValue = resultSet.getBigDecimal("discount_value"); final String voucherTypeName = resultSet.getString("voucher_type"); - final VoucherType voucherType = VoucherType.findVoucherTypeByName(voucherTypeName); + final VoucherType voucherType = VoucherType.findVoucherType(voucherTypeName); byte[] idBytes = resultSet.getBytes("customer_id"); final UUID customerId = idBytes != null ? UUIDConverter.from(idBytes) : null; return new Voucher(voucherId, createdAt, discountValue, voucherType, customerId); diff --git a/src/test/java/com/programmers/vouchermanagement/voucher/domain/VoucherTypeTest.java b/src/test/java/com/programmers/vouchermanagement/voucher/domain/VoucherTypeTest.java index 464aeb8eaf..9f5c5a31f8 100644 --- a/src/test/java/com/programmers/vouchermanagement/voucher/domain/VoucherTypeTest.java +++ b/src/test/java/com/programmers/vouchermanagement/voucher/domain/VoucherTypeTest.java @@ -16,7 +16,7 @@ void testFindVoucherTypeFailed_ReturnEmptyOptional() { String desiredVoucherType = "NoCount"; //when - assertThatThrownBy(() -> VoucherType.findVoucherTypeByName(desiredVoucherType)) + assertThatThrownBy(() -> VoucherType.findVoucherType(desiredVoucherType)) .isInstanceOf(IllegalArgumentException.class); } @@ -28,8 +28,8 @@ void testFindVoucherTypeSuccessful_LowerCase() { String percentType = "percent"; //when - VoucherType fixedVoucherType = VoucherType.findVoucherTypeByName(fixedType); - VoucherType percentVoucherType = VoucherType.findVoucherTypeByName(percentType); + VoucherType fixedVoucherType = VoucherType.findVoucherType(fixedType); + VoucherType percentVoucherType = VoucherType.findVoucherType(percentType); //then assertThat(fixedVoucherType, is(VoucherType.FIXED)); @@ -44,8 +44,8 @@ void testFindVoucherTypeSuccessful_CaseInsensitive() { String percentType = "PERCENT"; //when - VoucherType fixedVoucherType = VoucherType.findVoucherTypeByName(fixedType); - VoucherType percentVoucherType = VoucherType.findVoucherTypeByName(percentType); + VoucherType fixedVoucherType = VoucherType.findVoucherType(fixedType); + VoucherType percentVoucherType = VoucherType.findVoucherType(percentType); //then assertThat(fixedVoucherType, is(VoucherType.FIXED)); From 4687ebeae46a2096d6a89706a48a4ae6c24d0411 Mon Sep 17 00:00:00 2001 From: Jay Date: Sat, 4 Nov 2023 21:27:12 +0900 Subject: [PATCH 36/81] enhance: add validation to UpdateVoucherRequest --- .../voucher/dto/UpdateVoucherRequest.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/dto/UpdateVoucherRequest.java b/src/main/java/com/programmers/vouchermanagement/voucher/dto/UpdateVoucherRequest.java index 156c10f28f..bd73fb74f0 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/dto/UpdateVoucherRequest.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/dto/UpdateVoucherRequest.java @@ -2,5 +2,11 @@ import java.util.UUID; -public record UpdateVoucherRequest(UUID voucherId, long discountValue, String voucherType) { +import jakarta.validation.constraints.Min; +import jakarta.validation.constraints.NotBlank; + +public record UpdateVoucherRequest( + UUID voucherId, + @Min(value = 0, message = "Discount value must be greater than 0.") long discountValue, + @NotBlank(message = "Voucher type cannot be blank.") String voucherType) { } From f82fb085d4d893c8d48e2a58dc3d453b89c713fc Mon Sep 17 00:00:00 2001 From: Jay Date: Sat, 4 Nov 2023 21:27:46 +0900 Subject: [PATCH 37/81] refactor: simplify finding voucher type process to avoid exception --- .../vouchermanagement/voucher/domain/VoucherType.java | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/domain/VoucherType.java b/src/main/java/com/programmers/vouchermanagement/voucher/domain/VoucherType.java index 62bc018c2b..566b25161c 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/domain/VoucherType.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/domain/VoucherType.java @@ -56,10 +56,7 @@ private static VoucherType findVoucherTypeByCode(String input) { return Arrays.stream(VoucherType.values()) .filter(menu -> menu.isMatchingCode(input)) .findFirst() - .orElseThrow(() -> { - logger.error(INVALID_VOUCHER_TYPE_MESSAGE); - return new IllegalArgumentException(INVALID_VOUCHER_TYPE_MESSAGE); - }); + .orElseThrow(IllegalArgumentException::new); } private boolean isMatchingName(String input) { From 70074b4ae1284685061354093594a17d303e297b Mon Sep 17 00:00:00 2001 From: Jay Date: Sat, 4 Nov 2023 21:27:59 +0900 Subject: [PATCH 38/81] feat: implement update controller --- .../voucher/controller/VoucherAdminController.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherAdminController.java b/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherAdminController.java index 671e15f9ed..0e8ac69517 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherAdminController.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherAdminController.java @@ -3,12 +3,18 @@ import java.util.List; import java.util.UUID; +import jakarta.validation.Valid; + import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.ModelAttribute; 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 com.programmers.vouchermanagement.voucher.dto.UpdateVoucherRequest; import com.programmers.vouchermanagement.voucher.dto.VoucherResponse; import com.programmers.vouchermanagement.voucher.service.VoucherService; @@ -34,4 +40,11 @@ public String findById(@PathVariable UUID voucherId, Model model) { model.addAttribute("voucher", voucher); return "vouchers/voucher"; } + + @PostMapping("/update") + public String update(@Valid @ModelAttribute UpdateVoucherRequest request, Model model) { + VoucherResponse voucher = voucherService.update(request); + model.addAttribute("voucher", voucher); + return "redirect:/vouchers/" + voucher.voucherId(); + } } From 042bc35d200020a22ea74bc3b18f6af45cc07422 Mon Sep 17 00:00:00 2001 From: Jay Date: Sat, 4 Nov 2023 21:28:22 +0900 Subject: [PATCH 39/81] feat: implement voucher view to be enabled for update --- .../resources/templates/vouchers/voucher.html | 43 ++++++++++++------- 1 file changed, 27 insertions(+), 16 deletions(-) diff --git a/src/main/resources/templates/vouchers/voucher.html b/src/main/resources/templates/vouchers/voucher.html index 63346dbdaf..91a8477b39 100644 --- a/src/main/resources/templates/vouchers/voucher.html +++ b/src/main/resources/templates/vouchers/voucher.html @@ -12,39 +12,50 @@

Voucher Detail

-
-
+
+
- Voucher ID : + +
-
- Creation Datetime : +
+ Creation Datetime :
-
-
- Current Voucher Type : Discount Voucher + Current Voucher Type : Discount Voucher

- +
From 347ffdbb6448c1d743fcf2bf211e583d1ce470d2 Mon Sep 17 00:00:00 2001 From: Jay Date: Sat, 4 Nov 2023 21:51:16 +0900 Subject: [PATCH 40/81] feat: create empty voucher for thymeleaf --- .../vouchermanagement/voucher/domain/Voucher.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/domain/Voucher.java b/src/main/java/com/programmers/vouchermanagement/voucher/domain/Voucher.java index 039df751b8..695749ebb9 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/domain/Voucher.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/domain/Voucher.java @@ -11,6 +11,14 @@ public class Voucher { private final VoucherType voucherType; private final UUID customerId; + public Voucher() { + this.voucherId = null; + this.createdAt = null; + this.discountValue = null; + this.voucherType = null; + this.customerId = null; + } + public Voucher(UUID voucherId, BigDecimal discountValue, VoucherType voucherType) { this(voucherId, LocalDateTime.now(), discountValue, voucherType, null); } From f3a6e484ebae5cd65105c3bf1e5749c992bae51a Mon Sep 17 00:00:00 2001 From: Jay Date: Sat, 4 Nov 2023 21:52:27 +0900 Subject: [PATCH 41/81] feat: implement create voucher controller --- .../controller/VoucherAdminController.java | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherAdminController.java b/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherAdminController.java index 0e8ac69517..d2f4bffa73 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherAdminController.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherAdminController.java @@ -11,9 +11,10 @@ import org.springframework.web.bind.annotation.ModelAttribute; 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 com.programmers.vouchermanagement.voucher.domain.Voucher; +import com.programmers.vouchermanagement.voucher.dto.CreateVoucherRequest; import com.programmers.vouchermanagement.voucher.dto.UpdateVoucherRequest; import com.programmers.vouchermanagement.voucher.dto.VoucherResponse; import com.programmers.vouchermanagement.voucher.service.VoucherService; @@ -34,6 +35,19 @@ public String readAllVouchers(Model model) { return "vouchers/vouchers"; } + @GetMapping("/create") + public String create(Model model) { + model.addAttribute("voucher", new Voucher()); + return "vouchers/voucher"; + } + + @PostMapping("/create") + public String create(@ModelAttribute CreateVoucherRequest request, Model model) { + VoucherResponse voucher = voucherService.create(request); + model.addAttribute("voucher", voucher); + return "redirect:/vouchers/" + voucher.voucherId(); + } + @GetMapping("/{voucherId}") public String findById(@PathVariable UUID voucherId, Model model) { VoucherResponse voucher = voucherService.findById(voucherId); From eb7873aee2ca2ac8da7feb2cf9922198b8e6f898 Mon Sep 17 00:00:00 2001 From: Jay Date: Sat, 4 Nov 2023 21:52:42 +0900 Subject: [PATCH 42/81] enhance: enhance voucher view to work for creation --- src/main/resources/templates/vouchers/voucher.html | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/resources/templates/vouchers/voucher.html b/src/main/resources/templates/vouchers/voucher.html index 91a8477b39..56fac4f776 100644 --- a/src/main/resources/templates/vouchers/voucher.html +++ b/src/main/resources/templates/vouchers/voucher.html @@ -13,7 +13,9 @@

Voucher Detail

-
+
Date: Sat, 4 Nov 2023 23:42:04 +0900 Subject: [PATCH 43/81] feat: implement delete voucher controller --- .../voucher/controller/VoucherAdminController.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherAdminController.java b/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherAdminController.java index d2f4bffa73..ecab2beb77 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherAdminController.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherAdminController.java @@ -42,7 +42,7 @@ public String create(Model model) { } @PostMapping("/create") - public String create(@ModelAttribute CreateVoucherRequest request, Model model) { + public String create(@Valid @ModelAttribute CreateVoucherRequest request, Model model) { VoucherResponse voucher = voucherService.create(request); model.addAttribute("voucher", voucher); return "redirect:/vouchers/" + voucher.voucherId(); @@ -61,4 +61,10 @@ public String update(@Valid @ModelAttribute UpdateVoucherRequest request, Model model.addAttribute("voucher", voucher); return "redirect:/vouchers/" + voucher.voucherId(); } + + @PostMapping("/{voucherId}/delete") + public String deleteById(@PathVariable UUID voucherId) { + voucherService.deleteById(voucherId); + return "vouchers/deleted"; + } } From 3f88909f80ea20eb0f1406fb707b32c22bdf01a2 Mon Sep 17 00:00:00 2001 From: Jay Date: Sat, 4 Nov 2023 23:44:20 +0900 Subject: [PATCH 44/81] enhance: add delete functionality to voucher view --- src/main/resources/templates/vouchers/voucher.html | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/main/resources/templates/vouchers/voucher.html b/src/main/resources/templates/vouchers/voucher.html index 56fac4f776..3a0bdaaabd 100644 --- a/src/main/resources/templates/vouchers/voucher.html +++ b/src/main/resources/templates/vouchers/voucher.html @@ -59,6 +59,14 @@

Voucher Detail

Save Changes +
+
From 3a0fe249c124af62b351a8ebd113ecb5029c2509 Mon Sep 17 00:00:00 2001 From: Jay Date: Sat, 4 Nov 2023 23:44:33 +0900 Subject: [PATCH 45/81] feat: add deleted view --- .../resources/templates/vouchers/deleted.html | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 src/main/resources/templates/vouchers/deleted.html diff --git a/src/main/resources/templates/vouchers/deleted.html b/src/main/resources/templates/vouchers/deleted.html new file mode 100644 index 0000000000..285a26a8cc --- /dev/null +++ b/src/main/resources/templates/vouchers/deleted.html @@ -0,0 +1,20 @@ + + + + + + + Document + + +
+

Voucher has been successfully deleted!

+
+
+ +
+ + From 4c010acfe36884de0eb9fde6bddf45f60b0b78d9 Mon Sep 17 00:00:00 2001 From: Jay Date: Sat, 4 Nov 2023 23:47:45 +0900 Subject: [PATCH 46/81] feat: add onclick event callback for creation of a voucher --- src/main/resources/templates/vouchers/vouchers.html | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/main/resources/templates/vouchers/vouchers.html b/src/main/resources/templates/vouchers/vouchers.html index 3896fa2149..56d5fb1b05 100644 --- a/src/main/resources/templates/vouchers/vouchers.html +++ b/src/main/resources/templates/vouchers/vouchers.html @@ -20,9 +20,16 @@

All Vouchers

Discount Value Voucher Type
- + -
+
From 851139d2be5eae75becd90e3d4f426d083f22e8e Mon Sep 17 00:00:00 2001 From: Jay Date: Sat, 4 Nov 2023 23:48:12 +0900 Subject: [PATCH 47/81] fix: close the form element --- src/main/resources/templates/vouchers/voucher.html | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/resources/templates/vouchers/voucher.html b/src/main/resources/templates/vouchers/voucher.html index 3a0bdaaabd..3eb9de0dc2 100644 --- a/src/main/resources/templates/vouchers/voucher.html +++ b/src/main/resources/templates/vouchers/voucher.html @@ -67,6 +67,7 @@

Voucher Detail

+
From 8c9b70f67fd1414bcc58bb481a761981411ffe0b Mon Sep 17 00:00:00 2001 From: Jay Date: Sun, 5 Nov 2023 00:20:12 +0900 Subject: [PATCH 48/81] feat: implement customer admin controllers --- .../controller/CustomerAdminController.java | 73 +++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 src/main/java/com/programmers/vouchermanagement/customer/controller/CustomerAdminController.java diff --git a/src/main/java/com/programmers/vouchermanagement/customer/controller/CustomerAdminController.java b/src/main/java/com/programmers/vouchermanagement/customer/controller/CustomerAdminController.java new file mode 100644 index 0000000000..f6118ee088 --- /dev/null +++ b/src/main/java/com/programmers/vouchermanagement/customer/controller/CustomerAdminController.java @@ -0,0 +1,73 @@ +package com.programmers.vouchermanagement.customer.controller; + +import java.util.List; +import java.util.UUID; + +import jakarta.validation.Valid; + +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.ModelAttribute; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; + +import com.programmers.vouchermanagement.customer.domain.Customer; +import com.programmers.vouchermanagement.customer.dto.CustomerResponse; +import com.programmers.vouchermanagement.customer.dto.UpdateCustomerRequest; +import com.programmers.vouchermanagement.customer.service.CustomerService; +import com.programmers.vouchermanagement.voucher.domain.Voucher; +import com.programmers.vouchermanagement.voucher.dto.CreateVoucherRequest; +import com.programmers.vouchermanagement.voucher.dto.UpdateVoucherRequest; +import com.programmers.vouchermanagement.voucher.dto.VoucherResponse; + +@Controller +@RequestMapping("/customers") +public class CustomerAdminController { + private final CustomerService customerService; + + public CustomerAdminController(CustomerService customerService) { + this.customerService = customerService; + } + + @GetMapping + public String readAllCustomers(Model model) { + List customers = customerService.findAll(); + model.addAttribute("customers", customers); + return "customers/customers"; + } + + @GetMapping("/create") + public String create(Model model) { + model.addAttribute("customer", new Customer()); + return "customers/customer"; + } + + @PostMapping("/create") + public String create(String name, Model model) { + CustomerResponse customer = customerService.create(name); + model.addAttribute("customer", customer); + return "redirect:/customers/" + customer.customerId(); + } + + @GetMapping("/{customerId}") + public String findById(@PathVariable UUID customerId, Model model) { + CustomerResponse customer = customerService.findById(customerId); + model.addAttribute("customer", customer); + return "customers/customer"; + } + + @PostMapping("/update") + public String update(@Valid @ModelAttribute UpdateCustomerRequest request, Model model) { + CustomerResponse customer = customerService.update(request); + model.addAttribute("customer", customer); + return "redirect:/customers/" + customer.customerId(); + } + + @PostMapping("/{customerId}/delete") + public String deleteById(@PathVariable UUID customerId) { + customerService.deleteById(customerId); + return "customers/deleted"; + } +} From 76ab655f2ce72cb8b7e54ba5a13cdf7c0c9933aa Mon Sep 17 00:00:00 2001 From: Jay Date: Sun, 5 Nov 2023 00:20:44 +0900 Subject: [PATCH 49/81] style: specify title for deleted view --- src/main/resources/templates/vouchers/deleted.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/resources/templates/vouchers/deleted.html b/src/main/resources/templates/vouchers/deleted.html index 285a26a8cc..a5b133fa0c 100644 --- a/src/main/resources/templates/vouchers/deleted.html +++ b/src/main/resources/templates/vouchers/deleted.html @@ -5,7 +5,7 @@ - Document + Voucher Management Admin - Deleted
From 764ed32c0cd17c6ee21bf0c6ef15eff9615d0bba Mon Sep 17 00:00:00 2001 From: Jay Date: Sun, 5 Nov 2023 00:21:01 +0900 Subject: [PATCH 50/81] enhance: add back to list button --- .../resources/templates/vouchers/voucher.html | 115 +++++++++--------- 1 file changed, 60 insertions(+), 55 deletions(-) diff --git a/src/main/resources/templates/vouchers/voucher.html b/src/main/resources/templates/vouchers/voucher.html index 3eb9de0dc2..7f613ed357 100644 --- a/src/main/resources/templates/vouchers/voucher.html +++ b/src/main/resources/templates/vouchers/voucher.html @@ -13,61 +13,66 @@

Voucher Detail

-
-
- - -
-
- Creation Datetime : -
-
- - -
-
- - -
-
- Current Voucher Type : Discount Voucher -
-
- - -
-
- -
+ +
+
+
+ + +
+
+ Creation Datetime : +
+
+ + +
+
+ + +
+
+ Current Voucher Type : Discount Voucher +
+
+ + +
+
+ +
+
From 5a243d72c08be749467aef261cfad4cdc9014b76 Mon Sep 17 00:00:00 2001 From: Jay Date: Sun, 5 Nov 2023 00:21:19 +0900 Subject: [PATCH 51/81] feat: add back to home button --- src/main/resources/templates/vouchers/vouchers.html | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/main/resources/templates/vouchers/vouchers.html b/src/main/resources/templates/vouchers/vouchers.html index 56d5fb1b05..45abae8ad1 100644 --- a/src/main/resources/templates/vouchers/vouchers.html +++ b/src/main/resources/templates/vouchers/vouchers.html @@ -42,6 +42,13 @@

All Vouchers

+
+ +
From cd56a5416ffba57c0cec3bcb7f3e282148a5df63 Mon Sep 17 00:00:00 2001 From: Jay Date: Sun, 5 Nov 2023 00:21:52 +0900 Subject: [PATCH 52/81] feat: add button to move to customers view --- src/main/resources/templates/index.html | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/resources/templates/index.html b/src/main/resources/templates/index.html index 23e6619b3d..bf6086f155 100644 --- a/src/main/resources/templates/index.html +++ b/src/main/resources/templates/index.html @@ -19,6 +19,9 @@

Select Service Menu

+ From e7be225ff416563f1059e3b596495592da2d074e Mon Sep 17 00:00:00 2001 From: Jay Date: Sun, 5 Nov 2023 00:22:04 +0900 Subject: [PATCH 53/81] refactor: remove unused statements --- .../customer/controller/CustomerAdminController.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/customer/controller/CustomerAdminController.java b/src/main/java/com/programmers/vouchermanagement/customer/controller/CustomerAdminController.java index f6118ee088..5d27f7a38f 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/controller/CustomerAdminController.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/controller/CustomerAdminController.java @@ -17,10 +17,6 @@ import com.programmers.vouchermanagement.customer.dto.CustomerResponse; import com.programmers.vouchermanagement.customer.dto.UpdateCustomerRequest; import com.programmers.vouchermanagement.customer.service.CustomerService; -import com.programmers.vouchermanagement.voucher.domain.Voucher; -import com.programmers.vouchermanagement.voucher.dto.CreateVoucherRequest; -import com.programmers.vouchermanagement.voucher.dto.UpdateVoucherRequest; -import com.programmers.vouchermanagement.voucher.dto.VoucherResponse; @Controller @RequestMapping("/customers") From 71989c6f682e4c073c96bc505809cc3e524feac5 Mon Sep 17 00:00:00 2001 From: Jay Date: Sun, 5 Nov 2023 00:22:28 +0900 Subject: [PATCH 54/81] enhance: add empty constructor of Customer --- .../vouchermanagement/customer/domain/Customer.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/main/java/com/programmers/vouchermanagement/customer/domain/Customer.java b/src/main/java/com/programmers/vouchermanagement/customer/domain/Customer.java index 22fecfa53b..65c8f9fea2 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/domain/Customer.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/domain/Customer.java @@ -10,6 +10,12 @@ public class Customer { private final String name; private final CustomerType customerType; + public Customer() { + customerId = null; + name = null; + customerType = null; + } + public Customer(UUID customerId, String name) { this(customerId, name, CustomerType.NORMAL); } From 6120d16997a94ae9543c676f23bf471bf5e5efa4 Mon Sep 17 00:00:00 2001 From: Jay Date: Sun, 5 Nov 2023 00:22:45 +0900 Subject: [PATCH 55/81] feat: add similar views to that for vouchers --- .../templates/customers/customer.html | 78 +++++++++++++++++++ .../templates/customers/customers.html | 53 +++++++++++++ .../templates/customers/deleted.html | 20 +++++ 3 files changed, 151 insertions(+) create mode 100644 src/main/resources/templates/customers/customer.html create mode 100644 src/main/resources/templates/customers/customers.html create mode 100644 src/main/resources/templates/customers/deleted.html diff --git a/src/main/resources/templates/customers/customer.html b/src/main/resources/templates/customers/customer.html new file mode 100644 index 0000000000..23e896c1d7 --- /dev/null +++ b/src/main/resources/templates/customers/customer.html @@ -0,0 +1,78 @@ + + + + + + + customer Management Admin - Customer Detail + + +
+
+

Customer Detail

+
+
+
+ +
+
+
+
+ + +
+
+ + +
+
+ + +
+
+ This customer is customer. +
+
+ + +
+
+ +
+
+
+
+ + diff --git a/src/main/resources/templates/customers/customers.html b/src/main/resources/templates/customers/customers.html new file mode 100644 index 0000000000..a489a6260c --- /dev/null +++ b/src/main/resources/templates/customers/customers.html @@ -0,0 +1,53 @@ + + + + + + + customer Management Admin - Customers + + +
+
+

All Customers

+
+
+
+
+ Customer ID + Customer Name + Customer Type +
+ +
+
+
+ + + +
+ +
+
+ +
+
+
+ + diff --git a/src/main/resources/templates/customers/deleted.html b/src/main/resources/templates/customers/deleted.html new file mode 100644 index 0000000000..62d740474e --- /dev/null +++ b/src/main/resources/templates/customers/deleted.html @@ -0,0 +1,20 @@ + + + + + + + Voucher Management Admin - Deleted + + +
+

Customer has been successfully deleted!

+
+
+ +
+ + From 3e0e65fb47f87c5233fc99b4f7b86ac469327df1 Mon Sep 17 00:00:00 2001 From: Jay Date: Sun, 5 Nov 2023 02:24:59 +0900 Subject: [PATCH 56/81] style: update overall style --- src/main/resources/static/styles/common.css | 35 +++++ src/main/resources/static/styles/detail.css | 53 +++++++ src/main/resources/static/styles/index.css | 23 ++++ src/main/resources/static/styles/list.css | 79 +++++++++++ .../templates/customers/customer.html | 124 +++++++++-------- .../templates/customers/customers.html | 50 +++---- .../templates/customers/deleted.html | 1 + src/main/resources/templates/index.html | 5 +- .../resources/templates/vouchers/deleted.html | 1 + .../resources/templates/vouchers/voucher.html | 130 ++++++++++-------- .../templates/vouchers/vouchers.html | 54 ++++---- 11 files changed, 393 insertions(+), 162 deletions(-) create mode 100644 src/main/resources/static/styles/common.css create mode 100644 src/main/resources/static/styles/detail.css create mode 100644 src/main/resources/static/styles/index.css create mode 100644 src/main/resources/static/styles/list.css diff --git a/src/main/resources/static/styles/common.css b/src/main/resources/static/styles/common.css new file mode 100644 index 0000000000..fa12b22be6 --- /dev/null +++ b/src/main/resources/static/styles/common.css @@ -0,0 +1,35 @@ +@import url('https://fonts.googleapis.com/css2?family=Anton&family=Playpen+Sans:wght@400;600&display=swap'); + +@keyframes pulse { + 0% { box-shadow: 0 0 0 0 #eaf6f6; } +} + +body { + box-sizing: border-box; + font-family: 'Playpen Sans', cursive; + max-width: 1180px; + margin: 0 auto; +} + +button { + font-family: 'Playpen Sans', cursive; + padding: 1rem 0.5rem; + background-color: #ccf5f5; + border: 2px solid #ccf5f5; + border-radius: 10px; + margin-right: 0.5rem; + transition: transform 0.5s ease; + cursor: pointer; + &:hover { + animation: pulse 1s; + box-shadow: 0 0 0 50px transparent; + transform: translateY(-0.4rem) scale(1.05); + font-weight: 600; + color: black; + } +} + +a { + text-decoration-line: none; + color: #556175; +} diff --git a/src/main/resources/static/styles/detail.css b/src/main/resources/static/styles/detail.css new file mode 100644 index 0000000000..ddb75d9b63 --- /dev/null +++ b/src/main/resources/static/styles/detail.css @@ -0,0 +1,53 @@ +.voucher-detail-container header, .customer-detail-container header { + display: flex; + justify-content: center; + align-items: center; + margin: 4rem; + font-size: 1.4rem; +} + +.back-to-list-button { + padding: 1.5rem 0.7rem; + font-weight: 600; +} + +.customer-detail-box-wrapper, .voucher-detail-box-wrapper { + max-width: 760px; + margin: 0 auto; + border: 3px solid #556175; + border-radius: 10px; +} + +.customer-detail-box, .voucher-detail-box { + width: 80%; + margin: 1.5rem auto; +} + +.customer-detail-form, .voucher-detail-form { + display: flex; + flex-direction: column; + gap: 1.5rem; +} + +.customer-detail-form div, .voucher-detail-form div { + width: 70%; + margin: 0 auto; + display: flex; + justify-content: space-between; +} + +.customer-detail-form .button-wrapper, .voucher-detail-form .button-wrapper { + display: flex; + justify-content: center; + margin-bottom: 1.5rem; +} + +.delete-form { + display: flex; + justify-content: center; +} + +.delete-form button { + background-color: #e53c3c; + border: 2px solid #e53c3c; +} diff --git a/src/main/resources/static/styles/index.css b/src/main/resources/static/styles/index.css new file mode 100644 index 0000000000..cd9b4ab07b --- /dev/null +++ b/src/main/resources/static/styles/index.css @@ -0,0 +1,23 @@ +.main-container { + text-align: center; +} + +.admin-header { + margin: 5rem; + font-size: 2rem; +} + +.sub-header { + font-size: 1.5rem; + padding: 2rem 0; +} + +.menu-container { + width: 40%; + margin: 0 auto; +} + +.menu-wrapper { + display: flex; + justify-content: space-between; +} diff --git a/src/main/resources/static/styles/list.css b/src/main/resources/static/styles/list.css new file mode 100644 index 0000000000..e36b3deccf --- /dev/null +++ b/src/main/resources/static/styles/list.css @@ -0,0 +1,79 @@ +.voucher-page-container, .customer-page-container { +} + +.voucher-page-container header, .customer-page-container header { + display: flex; + justify-content: center; + align-items: center; + margin: 4rem; + font-size: 1.4rem; +} + +.vouchers-container, .customers-container { + font-size: 1.1rem; +} + +.voucher-item-header, .customer-item-header { + display: flex; + justify-content: space-between; + align-items: center; + font-weight: 600; + border-bottom: 2px solid #383841; + padding-bottom: 0.7rem; + margin-bottom: 1.5rem; +} + +.voucher-item-description, .customer-item-description, .voucher-item-detail, .customer-item-detail { + flex: 1; + display: flex; +} + +.voucher-id, .customer-id { + flex: 2 1 0; + text-align: center; +} + +.created-at { + flex: 1 1 0; +} + +.discount-value, .customer-name { + flex: 1 1 0; + text-align: center; +} + +.voucher-type, .customer-type{ + flex: 1 1 0; + text-align: center; +} + +.voucher-items, .customer-items { + display: flex; + flex-direction: column; + gap: 1rem; +} + +.voucher-item, .customer-item { + display: flex; + justify-content: space-between; + align-items: center; + border-bottom: 1px solid #555562; + padding-bottom: 0.7rem; +} + +.voucher-item-detail { + margin-right: 1rem; +} + +.customer-item-detail { + margin-right: 1.3rem; +} + +.voucher-detail-btn, .customer-detail-btn { + padding: 1.3rem 0.5rem; +} + +.back-to-home-button { + padding: 1.5rem 0.7rem; + font-weight: 600; +} diff --git a/src/main/resources/templates/customers/customer.html b/src/main/resources/templates/customers/customer.html index 23e896c1d7..d2bdf96732 100644 --- a/src/main/resources/templates/customers/customer.html +++ b/src/main/resources/templates/customers/customer.html @@ -5,72 +5,86 @@ + + customer Management Admin - Customer Detail -
+

Customer Detail

-
-
-
-
- - -
-
- - -
-
- - -
-
- This customer is customer. -
-
- - -
-
- -
+
+
+
+
+ + +
+
+ + +
+
+ + +
+
+ This customer is + + + + customer. +
+
+ + +
+
+ +
+
+
+ +
+
diff --git a/src/main/resources/templates/customers/customers.html b/src/main/resources/templates/customers/customers.html index a489a6260c..d6cb250831 100644 --- a/src/main/resources/templates/customers/customers.html +++ b/src/main/resources/templates/customers/customers.html @@ -5,6 +5,8 @@ + + customer Management Admin - Customers @@ -12,12 +14,19 @@

All Customers

+
+ +
- Customer ID - Customer Name - Customer Type + Customer ID + Customer Name + Customer Type
-
-
- - - -
- -
-
- +
+ + + +
+ +
diff --git a/src/main/resources/templates/customers/deleted.html b/src/main/resources/templates/customers/deleted.html index 62d740474e..724899efdc 100644 --- a/src/main/resources/templates/customers/deleted.html +++ b/src/main/resources/templates/customers/deleted.html @@ -5,6 +5,7 @@ + Voucher Management Admin - Deleted diff --git a/src/main/resources/templates/index.html b/src/main/resources/templates/index.html index bf6086f155..44970cd117 100644 --- a/src/main/resources/templates/index.html +++ b/src/main/resources/templates/index.html @@ -5,9 +5,12 @@ + + + Voucher Management Admin - +

Voucher Management Admin

diff --git a/src/main/resources/templates/vouchers/deleted.html b/src/main/resources/templates/vouchers/deleted.html index a5b133fa0c..1041d02ddd 100644 --- a/src/main/resources/templates/vouchers/deleted.html +++ b/src/main/resources/templates/vouchers/deleted.html @@ -5,6 +5,7 @@ + Voucher Management Admin - Deleted diff --git a/src/main/resources/templates/vouchers/voucher.html b/src/main/resources/templates/vouchers/voucher.html index 7f613ed357..be8a2d69d8 100644 --- a/src/main/resources/templates/vouchers/voucher.html +++ b/src/main/resources/templates/vouchers/voucher.html @@ -5,73 +5,87 @@ + + Voucher Management Admin - Voucher Detail -
+

Voucher Detail

- -
-
-
- - -
-
- Creation Datetime : -
-
- - -
-
- - -
-
- Current Voucher Type : Discount Voucher -
-
- - -
-
- -
+
+
+
+
+ + +
+
+ Creation Datetime : +
+
+ + +
+
+ + +
+
+ Current Voucher Type : + + + + Discount Voucher +
+
+ + +
+
+ +
+
+
+ +
+
diff --git a/src/main/resources/templates/vouchers/vouchers.html b/src/main/resources/templates/vouchers/vouchers.html index 45abae8ad1..1a02ce2bd4 100644 --- a/src/main/resources/templates/vouchers/vouchers.html +++ b/src/main/resources/templates/vouchers/vouchers.html @@ -5,6 +5,8 @@ + + Voucher Management Admin - Vouchers @@ -12,13 +14,20 @@

All Vouchers

+
+ +
- Voucher ID - Creation Datetime - Discount Value - Voucher Type + Voucher ID + Creation Datetime + Discount Value + Voucher Type
-
-
- - - - -
- -
-
- +
+ + + + +
+ +
From 4d6b85326142da9367fd8f3da5dc8549d813bc56 Mon Sep 17 00:00:00 2001 From: Jay Date: Sun, 5 Nov 2023 15:44:00 +0900 Subject: [PATCH 57/81] refactor: remove unnecessary empty list creation --- .../customer/repository/InMemoryCustomerRepository.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/customer/repository/InMemoryCustomerRepository.java b/src/main/java/com/programmers/vouchermanagement/customer/repository/InMemoryCustomerRepository.java index 59cc55dcdf..03c49e955b 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/repository/InMemoryCustomerRepository.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/repository/InMemoryCustomerRepository.java @@ -29,9 +29,6 @@ public Customer save(Customer customer) { @Override public List findAll() { - if (customers.isEmpty()) { - return Collections.emptyList(); - } return customers.values() .stream() .toList(); From 39ef1a3ad80570626ae2c66ed3d5ee0cf8b6631c Mon Sep 17 00:00:00 2001 From: Jay Date: Sun, 5 Nov 2023 15:57:45 +0900 Subject: [PATCH 58/81] refactor: fix header to be selective --- src/main/resources/templates/customers/customer.html | 2 +- src/main/resources/templates/vouchers/voucher.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/resources/templates/customers/customer.html b/src/main/resources/templates/customers/customer.html index d2bdf96732..260c002ce6 100644 --- a/src/main/resources/templates/customers/customer.html +++ b/src/main/resources/templates/customers/customer.html @@ -12,7 +12,7 @@
-

Customer Detail

+

diff --git a/src/main/resources/templates/vouchers/voucher.html b/src/main/resources/templates/vouchers/voucher.html index be8a2d69d8..6a1ab2e9bb 100644 --- a/src/main/resources/templates/vouchers/voucher.html +++ b/src/main/resources/templates/vouchers/voucher.html @@ -12,7 +12,7 @@
-

Voucher Detail

+

-
diff --git a/src/main/resources/templates/index.html b/src/main/resources/templates/index.html index 44970cd117..d4f9274739 100644 --- a/src/main/resources/templates/index.html +++ b/src/main/resources/templates/index.html @@ -19,11 +19,15 @@

Select Service Menu

diff --git a/src/main/resources/templates/vouchers/vouchers.html b/src/main/resources/templates/vouchers/vouchers.html index 1a02ce2bd4..0363903dbf 100644 --- a/src/main/resources/templates/vouchers/vouchers.html +++ b/src/main/resources/templates/vouchers/vouchers.html @@ -46,10 +46,10 @@

All Vouchers

-
From 775ab6d053e77d68d4e371e73d7f36004283e998 Mon Sep 17 00:00:00 2001 From: Jay Date: Sun, 5 Nov 2023 21:45:12 +0900 Subject: [PATCH 69/81] enhance: enable controllers for only web condition --- .../VoucherManagementApplication.java | 13 +++++++++++++ .../controller/CustomerAdminController.java | 2 ++ .../voucher/controller/VoucherAdminController.java | 2 ++ .../voucher/controller/VoucherRestController.java | 2 ++ 4 files changed, 19 insertions(+) diff --git a/src/main/java/com/programmers/vouchermanagement/VoucherManagementApplication.java b/src/main/java/com/programmers/vouchermanagement/VoucherManagementApplication.java index e4b73b8d04..0545ccd8e6 100644 --- a/src/main/java/com/programmers/vouchermanagement/VoucherManagementApplication.java +++ b/src/main/java/com/programmers/vouchermanagement/VoucherManagementApplication.java @@ -1,6 +1,7 @@ package com.programmers.vouchermanagement; import org.springframework.boot.SpringApplication; +import org.springframework.boot.WebApplicationType; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; import org.springframework.boot.context.properties.ConfigurationPropertiesScan; @@ -12,7 +13,19 @@ public class VoucherManagementApplication { public static void main(String[] args) { SpringApplication application = new SpringApplication(VoucherManagementApplication.class); application.setAdditionalProfiles("file"); + setApplicationMode(application); application.run(args); } + private static void setApplicationMode(SpringApplication application) { + if (isWebMode(application)) { + return; + } + application.setWebApplicationType(WebApplicationType.NONE); + } + + private static boolean isWebMode(SpringApplication application) { + return application.getAdditionalProfiles().contains("web"); + } + } diff --git a/src/main/java/com/programmers/vouchermanagement/customer/controller/CustomerAdminController.java b/src/main/java/com/programmers/vouchermanagement/customer/controller/CustomerAdminController.java index 5d27f7a38f..a86b8ba65d 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/controller/CustomerAdminController.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/controller/CustomerAdminController.java @@ -5,6 +5,7 @@ import jakarta.validation.Valid; +import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.GetMapping; @@ -19,6 +20,7 @@ import com.programmers.vouchermanagement.customer.service.CustomerService; @Controller +@ConditionalOnWebApplication @RequestMapping("/customers") public class CustomerAdminController { private final CustomerService customerService; diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherAdminController.java b/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherAdminController.java index ecab2beb77..722b92fb3d 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherAdminController.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherAdminController.java @@ -5,6 +5,7 @@ import jakarta.validation.Valid; +import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.GetMapping; @@ -20,6 +21,7 @@ import com.programmers.vouchermanagement.voucher.service.VoucherService; @Controller +@ConditionalOnWebApplication @RequestMapping("/vouchers") public class VoucherAdminController { private final VoucherService voucherService; diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherRestController.java b/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherRestController.java index 3ab2fab3f3..d0a5342507 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherRestController.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherRestController.java @@ -5,6 +5,7 @@ import jakarta.validation.Valid; +import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.web.bind.annotation.DeleteMapping; @@ -22,6 +23,7 @@ import com.programmers.vouchermanagement.voucher.service.VoucherService; @RestController +@ConditionalOnWebApplication @RequestMapping(value = "/api/v1/vouchers", produces = {MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE}) public class VoucherRestController { private final VoucherService voucherService; From 609c3c7656060de641e8fe1968e648495dbf16c8 Mon Sep 17 00:00:00 2001 From: Jay Date: Sun, 5 Nov 2023 22:39:19 +0900 Subject: [PATCH 70/81] feat: add general advice for thymeleaf error page --- .../advice/GeneralAdvice.java | 29 +++++++++++++++++++ ...{ControllerAdvice.java => RestAdvice.java} | 2 +- src/main/resources/templates/error.html | 21 ++++++++++++++ 3 files changed, 51 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/programmers/vouchermanagement/advice/GeneralAdvice.java rename src/main/java/com/programmers/vouchermanagement/advice/{ControllerAdvice.java => RestAdvice.java} (97%) create mode 100644 src/main/resources/templates/error.html diff --git a/src/main/java/com/programmers/vouchermanagement/advice/GeneralAdvice.java b/src/main/java/com/programmers/vouchermanagement/advice/GeneralAdvice.java new file mode 100644 index 0000000000..7fe7474492 --- /dev/null +++ b/src/main/java/com/programmers/vouchermanagement/advice/GeneralAdvice.java @@ -0,0 +1,29 @@ +package com.programmers.vouchermanagement.advice; + +import java.util.NoSuchElementException; + +import org.springframework.ui.Model; +import org.springframework.validation.BindingResult; +import org.springframework.validation.FieldError; +import org.springframework.web.bind.MethodArgumentNotValidException; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.bind.annotation.ExceptionHandler; + +@ControllerAdvice +public class GeneralAdvice { + + @ExceptionHandler({IllegalArgumentException.class, NoSuchElementException.class, RuntimeException.class}) + public String renderErrorPage(RuntimeException exception, Model model) { + model.addAttribute("message", exception.getMessage()); + return "error"; + } + + @ExceptionHandler(MethodArgumentNotValidException.class) + public String handleInvalidMethodArgumentException(BindingResult bindingResult, Model model) { + FieldError error = bindingResult.getFieldErrors() + .get(0); + String message = error.getField() + " exception - " + error.getDefaultMessage(); + model.addAttribute("message", message); + return "error"; + } +} diff --git a/src/main/java/com/programmers/vouchermanagement/advice/ControllerAdvice.java b/src/main/java/com/programmers/vouchermanagement/advice/RestAdvice.java similarity index 97% rename from src/main/java/com/programmers/vouchermanagement/advice/ControllerAdvice.java rename to src/main/java/com/programmers/vouchermanagement/advice/RestAdvice.java index 5bbaeced21..0f512c3a55 100644 --- a/src/main/java/com/programmers/vouchermanagement/advice/ControllerAdvice.java +++ b/src/main/java/com/programmers/vouchermanagement/advice/RestAdvice.java @@ -11,7 +11,7 @@ import org.springframework.web.bind.annotation.RestControllerAdvice; @RestControllerAdvice -public class ControllerAdvice { +public class RestAdvice { @ExceptionHandler(MethodArgumentNotValidException.class) @ResponseStatus(HttpStatus.BAD_REQUEST) diff --git a/src/main/resources/templates/error.html b/src/main/resources/templates/error.html new file mode 100644 index 0000000000..f5281f7f2d --- /dev/null +++ b/src/main/resources/templates/error.html @@ -0,0 +1,21 @@ + + + + + + + + Voucher Management Admin - Error + + +
+

Error Happened!

+
+
+ +
+ + From c245c62c2d478988979b259fa8076062b556ac36 Mon Sep 17 00:00:00 2001 From: Jay Date: Sun, 5 Nov 2023 22:55:10 +0900 Subject: [PATCH 71/81] fix: disable name to be blank --- .../vouchermanagement/customer/domain/Customer.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/main/java/com/programmers/vouchermanagement/customer/domain/Customer.java b/src/main/java/com/programmers/vouchermanagement/customer/domain/Customer.java index 65c8f9fea2..9a9382d9bc 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/domain/Customer.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/domain/Customer.java @@ -5,6 +5,7 @@ public class Customer { private static final int MAX_NAME_LENGTH = 25; private static final String NAME_LENGTH_EXCESSIVE = "Name is too long."; + private static final String NAME_BLANK = "Blank name is invalid."; private final UUID customerId; private final String name; @@ -44,9 +45,20 @@ public boolean isBlack() { } private void validateCustomerName(String name) { + validateNameExcessive(name); + validateNameBlank(name); + } + + private void validateNameExcessive(String name) { if (name.length() > MAX_NAME_LENGTH) { throw new IllegalArgumentException(NAME_LENGTH_EXCESSIVE); } } + + private void validateNameBlank(String name) { + if (name.isBlank()) { + throw new IllegalArgumentException(NAME_BLANK); + } + } } From 40cbeeda5a9a70385bf281e4e6a5623e97e24be6 Mon Sep 17 00:00:00 2001 From: Jay Date: Sun, 5 Nov 2023 23:24:38 +0900 Subject: [PATCH 72/81] chore: create dockerfile and update to proper mysql url --- Dockerfile | 6 ++++++ src/main/resources/application.yaml | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) create mode 100644 Dockerfile diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000000..2412e7a3dd --- /dev/null +++ b/Dockerfile @@ -0,0 +1,6 @@ +FROM mysql:latest + +ENV MYSQL_ROOT_PASSWORD=1234 +ENV MYSQL_DATABASE=voucher_management + +COPY ./init.sql /docker-entrypoint-initdb.d/ diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index 6b76a45a4f..c75bca85e5 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -1,5 +1,5 @@ datasource: - url: jdbc:mysql://localhost:3305/voucher_management + url: jdbc:mysql://localhost:33060/voucher_management username: root password: 1234 From d38611f358e66363ffedd16deb7a6043a8d4ad1c Mon Sep 17 00:00:00 2001 From: Jay Date: Sun, 5 Nov 2023 23:29:10 +0900 Subject: [PATCH 73/81] enhance: advise only RestControllers --- .../com/programmers/vouchermanagement/advice/RestAdvice.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/programmers/vouchermanagement/advice/RestAdvice.java b/src/main/java/com/programmers/vouchermanagement/advice/RestAdvice.java index 0f512c3a55..5c5dd6ca0b 100644 --- a/src/main/java/com/programmers/vouchermanagement/advice/RestAdvice.java +++ b/src/main/java/com/programmers/vouchermanagement/advice/RestAdvice.java @@ -8,9 +8,10 @@ import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestControllerAdvice; -@RestControllerAdvice +@RestControllerAdvice(annotations = RestController.class) public class RestAdvice { @ExceptionHandler(MethodArgumentNotValidException.class) From e9fd57719910b2db8bdf40cf8a954f5736f72a37 Mon Sep 17 00:00:00 2001 From: Jay Date: Sun, 5 Nov 2023 23:29:35 +0900 Subject: [PATCH 74/81] chore: add init.sql for Dockerfile building --- init.sql | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 init.sql diff --git a/init.sql b/init.sql new file mode 100644 index 0000000000..3d08a794ca --- /dev/null +++ b/init.sql @@ -0,0 +1,14 @@ +CREATE TABLE customers ( + customer_id BINARY(16) PRIMARY KEY, + name VARCHAR(30) NOT NULL, + customer_type VARCHAR(10) NOT NULL default 'NORMAL' +); + +CREATE TABLE vouchers ( + voucher_id BINARY(16) PRIMARY KEY, + created_at DATETIME NOT NULL, + discount_value DECIMAL NOT NULL, + voucher_type VARCHAR(10) NOT NULL, + customer_id BINARY(16), + FOREIGN KEY (customer_id) REFERENCES customers(customer_id) +) From c1b6ca7427443150b75c559caccc14da0661f5d1 Mon Sep 17 00:00:00 2001 From: Jay Date: Sun, 5 Nov 2023 23:45:48 +0900 Subject: [PATCH 75/81] enhance: add transactional --- .../customer/service/CustomerService.java | 8 ++++++++ .../voucher/service/VoucherService.java | 11 +++++++++++ 2 files changed, 19 insertions(+) diff --git a/src/main/java/com/programmers/vouchermanagement/customer/service/CustomerService.java b/src/main/java/com/programmers/vouchermanagement/customer/service/CustomerService.java index 10e00c509a..8367558644 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/service/CustomerService.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/service/CustomerService.java @@ -5,6 +5,7 @@ import java.util.UUID; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import com.programmers.vouchermanagement.customer.domain.Customer; import com.programmers.vouchermanagement.customer.dto.CustomerResponse; @@ -23,6 +24,7 @@ public CustomerService(CustomerRepository customerRepository, VoucherRepository this.voucherRepository = voucherRepository; } + @Transactional(readOnly = true) public List readBlacklist() { List blacklist = customerRepository.findBlackCustomers(); return blacklist.stream() @@ -30,12 +32,14 @@ public List readBlacklist() { .toList(); } + @Transactional public CustomerResponse create(String name) { Customer customer = new Customer(UUID.randomUUID(), name); customerRepository.save(customer); return CustomerResponse.from(customer); } + @Transactional(readOnly = true) public List findAll() { List customers = customerRepository.findAll(); return customers.stream() @@ -43,12 +47,14 @@ public List findAll() { .toList(); } + @Transactional(readOnly = true) public CustomerResponse findById(UUID customerId) { Customer customer = customerRepository.findById(customerId) .orElseThrow(() -> new NoSuchElementException("There is no customer with %s".formatted(customerId))); return CustomerResponse.from(customer); } + @Transactional public CustomerResponse update(UpdateCustomerRequest request) { validateIdExisting(request.customerId()); Customer customer = new Customer(request.customerId(), request.name(), request.customerType()); @@ -56,11 +62,13 @@ public CustomerResponse update(UpdateCustomerRequest request) { return CustomerResponse.from(updatedCustomer); } + @Transactional public void deleteById(UUID customerId) { validateIdExisting(customerId); customerRepository.deleteById(customerId); } + @Transactional(readOnly = true) public CustomerResponse findByVoucherId(UUID voucherId) { Voucher voucher = voucherRepository.findById(voucherId) .orElseThrow(() -> new NoSuchElementException(("There is no voucher with %s").formatted(voucherId))); diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java b/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java index 64979f6746..0fc438bf11 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/service/VoucherService.java @@ -8,6 +8,7 @@ import java.util.UUID; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import com.programmers.vouchermanagement.customer.domain.Customer; import com.programmers.vouchermanagement.customer.repository.CustomerRepository; @@ -30,6 +31,7 @@ public VoucherService(VoucherRepository voucherRepository, CustomerRepository cu this.customerRepository = customerRepository; } + @Transactional public VoucherResponse create(CreateVoucherRequest request) { VoucherType voucherType = VoucherType.findVoucherType(request.voucherType()); Voucher voucher = new Voucher(UUID.randomUUID(), new BigDecimal(request.discountValue()), voucherType); @@ -37,6 +39,7 @@ public VoucherResponse create(CreateVoucherRequest request) { return VoucherResponse.from(voucher); } + @Transactional(readOnly = true) public List readAllVouchers() { List vouchers = voucherRepository.findAll(); return vouchers.stream() @@ -44,6 +47,7 @@ public List readAllVouchers() { .toList(); } + @Transactional(readOnly = true) public List findByType(VoucherType voucherType) { List vouchers = voucherRepository.findByType(voucherType); return vouchers.stream() @@ -51,6 +55,7 @@ public List findByType(VoucherType voucherType) { .toList(); } + @Transactional(readOnly = true) public List findByCreatedAt(SearchCreatedAtRequest request) { validateDateRange(request); LocalDateTime startDateTime = request.startDate().atStartOfDay(); @@ -61,12 +66,14 @@ public List findByCreatedAt(SearchCreatedAtRequest request) { .toList(); } + @Transactional(readOnly = true) public VoucherResponse findById(UUID voucherId) { Voucher voucher = voucherRepository.findById(voucherId) .orElseThrow(() -> new NoSuchElementException("There is no voucher with %s".formatted(voucherId))); return VoucherResponse.from(voucher); } + @Transactional public VoucherResponse update(UpdateVoucherRequest request) { validateVoucherIdExisting(request.voucherId()); VoucherType voucherType = VoucherType.findVoucherType(request.voucherType()); @@ -75,11 +82,13 @@ public VoucherResponse update(UpdateVoucherRequest request) { return VoucherResponse.from(updatedVoucher); } + @Transactional public void deleteById(UUID voucherId) { validateVoucherIdExisting(voucherId); voucherRepository.deleteById(voucherId); } + @Transactional public void grantToCustomer(VoucherCustomerRequest request) { validateCustomerIdExisting(request.customerId()); VoucherResponse foundVoucher = findById(request.voucherId()); @@ -93,6 +102,7 @@ public void grantToCustomer(VoucherCustomerRequest request) { voucherRepository.save(voucher); } + @Transactional public void releaseFromCustomer(VoucherCustomerRequest request) { validateCustomerIdExisting(request.customerId()); VoucherResponse foundVoucher = findById(request.voucherId()); @@ -106,6 +116,7 @@ public void releaseFromCustomer(VoucherCustomerRequest request) { voucherRepository.save(voucher); } + @Transactional(readOnly = true) public List findByCustomerId(UUID customerId) { Customer customer = customerRepository.findById(customerId) .orElseThrow(() -> new NoSuchElementException("There is no customer with %s".formatted(customerId))); From 98d87e8b0c723021c116353d2944f6c5bced4101 Mon Sep 17 00:00:00 2001 From: Jay Date: Mon, 6 Nov 2023 00:13:47 +0900 Subject: [PATCH 76/81] enhance: enable general advice to advise only admin controllers --- .../vouchermanagement/advice/GeneralAdvice.java | 4 +++- .../advice/annotation/AdminController.java | 16 ++++++++++++++++ .../controller/CustomerAdminController.java | 4 ++-- .../controller/VoucherAdminController.java | 4 ++-- 4 files changed, 23 insertions(+), 5 deletions(-) create mode 100644 src/main/java/com/programmers/vouchermanagement/advice/annotation/AdminController.java diff --git a/src/main/java/com/programmers/vouchermanagement/advice/GeneralAdvice.java b/src/main/java/com/programmers/vouchermanagement/advice/GeneralAdvice.java index 7fe7474492..df23d95f08 100644 --- a/src/main/java/com/programmers/vouchermanagement/advice/GeneralAdvice.java +++ b/src/main/java/com/programmers/vouchermanagement/advice/GeneralAdvice.java @@ -9,7 +9,9 @@ import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; -@ControllerAdvice +import com.programmers.vouchermanagement.advice.annotation.AdminController; + +@ControllerAdvice(annotations = AdminController.class) public class GeneralAdvice { @ExceptionHandler({IllegalArgumentException.class, NoSuchElementException.class, RuntimeException.class}) diff --git a/src/main/java/com/programmers/vouchermanagement/advice/annotation/AdminController.java b/src/main/java/com/programmers/vouchermanagement/advice/annotation/AdminController.java new file mode 100644 index 0000000000..46b822b570 --- /dev/null +++ b/src/main/java/com/programmers/vouchermanagement/advice/annotation/AdminController.java @@ -0,0 +1,16 @@ +package com.programmers.vouchermanagement.advice.annotation; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import org.springframework.stereotype.Controller; + +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@Controller +public @interface AdminController { +} diff --git a/src/main/java/com/programmers/vouchermanagement/customer/controller/CustomerAdminController.java b/src/main/java/com/programmers/vouchermanagement/customer/controller/CustomerAdminController.java index a86b8ba65d..d1845e8752 100644 --- a/src/main/java/com/programmers/vouchermanagement/customer/controller/CustomerAdminController.java +++ b/src/main/java/com/programmers/vouchermanagement/customer/controller/CustomerAdminController.java @@ -6,7 +6,6 @@ import jakarta.validation.Valid; import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; -import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.ModelAttribute; @@ -14,12 +13,13 @@ import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; +import com.programmers.vouchermanagement.advice.annotation.AdminController; import com.programmers.vouchermanagement.customer.domain.Customer; import com.programmers.vouchermanagement.customer.dto.CustomerResponse; import com.programmers.vouchermanagement.customer.dto.UpdateCustomerRequest; import com.programmers.vouchermanagement.customer.service.CustomerService; -@Controller +@AdminController @ConditionalOnWebApplication @RequestMapping("/customers") public class CustomerAdminController { diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherAdminController.java b/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherAdminController.java index 722b92fb3d..912f3a02d8 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherAdminController.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherAdminController.java @@ -6,7 +6,6 @@ import jakarta.validation.Valid; import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; -import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.ModelAttribute; @@ -14,13 +13,14 @@ import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; +import com.programmers.vouchermanagement.advice.annotation.AdminController; import com.programmers.vouchermanagement.voucher.domain.Voucher; import com.programmers.vouchermanagement.voucher.dto.CreateVoucherRequest; import com.programmers.vouchermanagement.voucher.dto.UpdateVoucherRequest; import com.programmers.vouchermanagement.voucher.dto.VoucherResponse; import com.programmers.vouchermanagement.voucher.service.VoucherService; -@Controller +@AdminController @ConditionalOnWebApplication @RequestMapping("/vouchers") public class VoucherAdminController { From 249bd533a143ebec10ac80b2c9f7cd5c9a753f50 Mon Sep 17 00:00:00 2001 From: Jay Date: Mon, 6 Nov 2023 00:14:27 +0900 Subject: [PATCH 77/81] refactor: merge find all api end points into one --- .../controller/VoucherRestController.java | 25 +++++++++++++------ .../voucher/dto/SearchCreatedAtRequest.java | 7 +----- 2 files changed, 19 insertions(+), 13 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherRestController.java b/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherRestController.java index d0a5342507..16becb9c84 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherRestController.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherRestController.java @@ -1,5 +1,6 @@ package com.programmers.vouchermanagement.voucher.controller; +import java.time.LocalDate; import java.util.List; import java.util.UUID; @@ -13,6 +14,7 @@ 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.ResponseStatus; import org.springframework.web.bind.annotation.RestController; @@ -40,7 +42,19 @@ public VoucherResponse create(@Valid CreateVoucherRequest createVoucherRequest) @GetMapping @ResponseStatus(HttpStatus.OK) - public List readAllVouchers() { + public List readAllVouchers( + @RequestParam(value = "typeName", required = false) String typeName, + @RequestParam(value = "startDate", required = false) LocalDate startDate, + @RequestParam(value = "endDate", required = false) LocalDate endDate + ) { + if (typeName != null) { + return findByType(typeName); + } + + if (startDate != null && endDate != null) { + return findByCreatedAt(startDate, endDate); + } + return voucherService.readAllVouchers(); } @@ -56,16 +70,13 @@ public void deleteById(@PathVariable UUID voucherId) { voucherService.deleteById(voucherId); } - @GetMapping("/type/{typeName}") - @ResponseStatus(HttpStatus.OK) - public List findByType(@PathVariable String typeName) { + private List findByType(String typeName) { VoucherType voucherType = VoucherType.findVoucherType(typeName); return voucherService.findByType(voucherType); } - @GetMapping("/creation-date") - @ResponseStatus(HttpStatus.OK) - public List findByCreatedAt(@Valid SearchCreatedAtRequest request) { + private List findByCreatedAt(LocalDate startDate, LocalDate endDate) { + SearchCreatedAtRequest request = new SearchCreatedAtRequest(startDate, endDate); return voucherService.findByCreatedAt(request); } } diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/dto/SearchCreatedAtRequest.java b/src/main/java/com/programmers/vouchermanagement/voucher/dto/SearchCreatedAtRequest.java index 849f2dc8ed..0f2e7b0c8b 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/dto/SearchCreatedAtRequest.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/dto/SearchCreatedAtRequest.java @@ -2,10 +2,5 @@ import java.time.LocalDate; -import jakarta.validation.constraints.NotBlank; - -public record SearchCreatedAtRequest( - @NotBlank(message = "Start-date cannot be blank.") LocalDate startDate, - @NotBlank(message = "End-date cannot be blank.") LocalDate endDate -) { +public record SearchCreatedAtRequest(LocalDate startDate, LocalDate endDate) { } From 58ba53233a5f83ac399e59719e2836c0ddf6dfbd Mon Sep 17 00:00:00 2001 From: Jay Date: Mon, 6 Nov 2023 00:23:33 +0900 Subject: [PATCH 78/81] refactor: remove unnecessary request param --- .../controller/VoucherRestController.java | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherRestController.java b/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherRestController.java index 16becb9c84..6bd657d1c5 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherRestController.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherRestController.java @@ -42,16 +42,12 @@ public VoucherResponse create(@Valid CreateVoucherRequest createVoucherRequest) @GetMapping @ResponseStatus(HttpStatus.OK) - public List readAllVouchers( - @RequestParam(value = "typeName", required = false) String typeName, - @RequestParam(value = "startDate", required = false) LocalDate startDate, - @RequestParam(value = "endDate", required = false) LocalDate endDate - ) { - if (typeName != null) { + public List readAllVouchers(String typeName, LocalDate startDate, LocalDate endDate) { + if (isSearchingType(typeName)) { return findByType(typeName); } - if (startDate != null && endDate != null) { + if (isSearchingDate(startDate, endDate)) { return findByCreatedAt(startDate, endDate); } @@ -70,6 +66,14 @@ public void deleteById(@PathVariable UUID voucherId) { voucherService.deleteById(voucherId); } + private boolean isSearchingType(String typeName) { + return typeName != null; + } + + private boolean isSearchingDate(LocalDate startDate, LocalDate endDate) { + return startDate != null && endDate != null; + } + private List findByType(String typeName) { VoucherType voucherType = VoucherType.findVoucherType(typeName); return voucherService.findByType(voucherType); From 46ff56929ff177f849c1928c88469f91c7e32e01 Mon Sep 17 00:00:00 2001 From: Jay Date: Mon, 6 Nov 2023 00:23:33 +0900 Subject: [PATCH 79/81] refactor: remove unnecessary request param --- .../controller/VoucherRestController.java | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherRestController.java b/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherRestController.java index 16becb9c84..4483a14da8 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherRestController.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherRestController.java @@ -14,7 +14,6 @@ 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.ResponseStatus; import org.springframework.web.bind.annotation.RestController; @@ -42,16 +41,12 @@ public VoucherResponse create(@Valid CreateVoucherRequest createVoucherRequest) @GetMapping @ResponseStatus(HttpStatus.OK) - public List readAllVouchers( - @RequestParam(value = "typeName", required = false) String typeName, - @RequestParam(value = "startDate", required = false) LocalDate startDate, - @RequestParam(value = "endDate", required = false) LocalDate endDate - ) { - if (typeName != null) { + public List readAllVouchers(String typeName, LocalDate startDate, LocalDate endDate) { + if (isSearchingType(typeName)) { return findByType(typeName); } - if (startDate != null && endDate != null) { + if (isSearchingDate(startDate, endDate)) { return findByCreatedAt(startDate, endDate); } @@ -70,6 +65,14 @@ public void deleteById(@PathVariable UUID voucherId) { voucherService.deleteById(voucherId); } + private boolean isSearchingType(String typeName) { + return typeName != null; + } + + private boolean isSearchingDate(LocalDate startDate, LocalDate endDate) { + return startDate != null && endDate != null; + } + private List findByType(String typeName) { VoucherType voucherType = VoucherType.findVoucherType(typeName); return voucherService.findByType(voucherType); From 2d85816df6c3500fc3215a5db2007e4a09fea6f9 Mon Sep 17 00:00:00 2001 From: Jay Date: Tue, 21 Nov 2023 10:47:13 +0900 Subject: [PATCH 80/81] feat: handle unexpected error --- .../programmers/vouchermanagement/advice/RestAdvice.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/main/java/com/programmers/vouchermanagement/advice/RestAdvice.java b/src/main/java/com/programmers/vouchermanagement/advice/RestAdvice.java index 5c5dd6ca0b..7369088130 100644 --- a/src/main/java/com/programmers/vouchermanagement/advice/RestAdvice.java +++ b/src/main/java/com/programmers/vouchermanagement/advice/RestAdvice.java @@ -34,4 +34,10 @@ public ExceptionMessage handleIllegalArgumentException(IllegalArgumentException public ExceptionMessage handleNoSuchElementException(NoSuchElementException exception) { return new ExceptionMessage(exception.getMessage()); } + + @ExceptionHandler(RuntimeException.class) + @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) + public ExceptionMessage handleRuntimeException(RuntimeException exception) { + return new ExceptionMessage("Unexpected message appears. Please contact to DEV team"); + } } From 34aecf0d3ab902dda66494bf9b51939ec861db95 Mon Sep 17 00:00:00 2001 From: Jay Date: Tue, 21 Nov 2023 10:58:41 +0900 Subject: [PATCH 81/81] fix: fix the improper http response status --- .../voucher/controller/VoucherRestController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherRestController.java b/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherRestController.java index 4483a14da8..86b0c11bdb 100644 --- a/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherRestController.java +++ b/src/main/java/com/programmers/vouchermanagement/voucher/controller/VoucherRestController.java @@ -60,7 +60,7 @@ public VoucherResponse findById(@PathVariable UUID voucherId) { } @DeleteMapping("/{voucherId}") - @ResponseStatus(HttpStatus.ACCEPTED) + @ResponseStatus(HttpStatus.NO_CONTENT) public void deleteById(@PathVariable UUID voucherId) { voucherService.deleteById(voucherId); }