Merge remote-tracking branch 'origin/main'

# Conflicts:
#	backend/user-service/src/main/resources/application.yml
This commit is contained in:
jooho
2021-10-28 10:58:33 +09:00
66 changed files with 1800 additions and 885 deletions

View File

@@ -1,8 +1,8 @@
# openjdk8 base image # openjdk8 base image
FROM openjdk:8-jre-alpine FROM openjdk:8-jre-alpine
# config server uri: dockder run --e 로 변경 가능 # directory 생성
ENV SPRING_CLOUD_CONFIG_URI https://egov-config.paas-ta.org RUN mkdir -p /usr/app/msa-attach-volume/messages
# jar 파일이 복사되는 위치 # jar 파일이 복사되는 위치
ENV APP_HOME=/usr/app/ ENV APP_HOME=/usr/app/
# 작업 시작 위치 # 작업 시작 위치
@@ -11,5 +11,5 @@ WORKDIR $APP_HOME
COPY build/libs/*.jar apigateway.jar COPY build/libs/*.jar apigateway.jar
# application port # application port
EXPOSE 8000 EXPOSE 8000
# 실행 (application-cf.yml 프로필이 기본값) # 실행
CMD ["java", "-Dspring.profiles.active=${profile:cf}", "-jar", "apigateway.jar"] CMD ["java", "-Dspring.profiles.active=${profile:default}", "-jar", "apigateway.jar"]

View File

@@ -10,7 +10,7 @@ applications:
- egov-discovery-provided-service # discovery service binding - egov-discovery-provided-service # discovery service binding
env: env:
spring_profiles_active: cf spring_profiles_active: cf
spring_cloud_config_uri: https://egov-config.paas-ta.org spring_cloud_config_uri: http://localhost:8888
app_name: egov-apigateway # logstash custom app name app_name: egov-apigateway # logstash custom app name
TZ: Asia/Seoul TZ: Asia/Seoul
JAVA_OPTS: -Xss349k JAVA_OPTS: -Xss349k

View File

@@ -36,7 +36,7 @@ import java.nio.file.Paths;
@Configuration @Configuration
public class MessageSourceConfig { public class MessageSourceConfig {
@Value("${messages.directory}") @Value("${messages.directory:${user.home}/msa-attach-volume/messages}")
private String messagesDirectory; private String messagesDirectory;
@Value("${spring.profiles.active:default}") @Value("${spring.profiles.active:default}")

View File

@@ -65,3 +65,6 @@ management:
web: web:
exposure: exposure:
include: refresh, health, beans include: refresh, health, beans
messages:
directory: ${user.dir}/msa-attach-volume/messages

View File

@@ -2,4 +2,4 @@ spring:
cloud: cloud:
config: config:
uri: http://localhost:8888 uri: http://localhost:8888
name: apigateway name: application

View File

@@ -15,7 +15,7 @@
</springProfile> </springProfile>
<springProfile name="!default"> <springProfile name="!default">
<!-- java -Ddestination="localhost:5001" 와 같이 변경할 수 있다. cf 환경에서는 manifest.yml 파일에 환경변수로 추가 --> <!-- java -Ddestination="localhost:5001" 와 같이 변경할 수 있다. cf 환경에서는 manifest.yml 파일에 환경변수로 추가 -->
<property name="destination" value="${destination:-localhost:5001}" /> <property name="destination" value="${logstash_hostname:-localhost:5001}" />
<property name="app_name" value="${app_name:-apigateway}" /> <property name="app_name" value="${app_name:-apigateway}" />
<!-- ELK - Logstash 로 로그를 전송하기 위한 appender --> <!-- ELK - Logstash 로 로그를 전송하기 위한 appender -->

View File

@@ -1,8 +1,8 @@
# openjdk8 base image # openjdk8 base image
FROM openjdk:8-jre-alpine FROM openjdk:8-jre-alpine
# config server uri: dockder run --e 로 변경 가능 # directory 생성
ENV SPRING_CLOUD_CONFIG_URI https://egov-config.paas-ta.org RUN mkdir -p /usr/app/msa-attach-volume/messages
# jar 파일이 복사되는 위치 # jar 파일이 복사되는 위치
ENV APP_HOME=/usr/app/ ENV APP_HOME=/usr/app/
# 작업 시작 위치 # 작업 시작 위치
@@ -11,5 +11,5 @@ WORKDIR $APP_HOME
COPY build/libs/*.jar app.jar COPY build/libs/*.jar app.jar
# application port # application port
#EXPOSE 8000 #EXPOSE 8000
# 실행 (application-cf.yml 프로필이 기본값) # 실행
CMD ["java", "-Dspring.profiles.active=${profile:cf}", "-jar", "app.jar"] CMD ["java", "-Dspring.profiles.active=${profile:default}", "-jar", "app.jar"]

View File

@@ -10,7 +10,7 @@ applications:
- egov-discovery-provided-service # discovery service binding - egov-discovery-provided-service # discovery service binding
env: env:
spring_profiles_active: cf spring_profiles_active: cf
spring_cloud_config_uri: https://egov-config.paas-ta.org spring_cloud_config_uri: http://localhost:8888
app_name: egov-board-service # logstash custom app name app_name: egov-board-service # logstash custom app name
TZ: Asia/Seoul TZ: Asia/Seoul
JAVA_OPTS: -Xss349k JAVA_OPTS: -Xss349k

View File

@@ -15,7 +15,7 @@
</springProfile> </springProfile>
<springProfile name="!default"> <springProfile name="!default">
<!-- java -Ddestination="localhost:5001" 와 같이 변경할 수 있다. cf 환경에서는 manifest.yml 파일에 환경변수로 추가 --> <!-- java -Ddestination="localhost:5001" 와 같이 변경할 수 있다. cf 환경에서는 manifest.yml 파일에 환경변수로 추가 -->
<property name="destination" value="${destination:-localhost:5001}" /> <property name="destination" value="${logstash_hostname:-localhost:5001}" />
<property name="app_name" value="${app_name:-board-service}" /> <property name="app_name" value="${app_name:-board-service}" />
<!-- ELK - Logstash 로 로그를 전송하기 위한 appender --> <!-- ELK - Logstash 로 로그를 전송하기 위한 appender -->

View File

@@ -1,6 +1,9 @@
# docker run --name egov-config -d -p 8888:8888 -e profile=prod -e ENCRYPT_KEY=??? egovframework/egov-config # docker run --name egov-config -d -p 8888:8888 -e profile=prod -e ENCRYPT_KEY=??? egovframework/egov-config
# base image - openjdk8 # base image - openjdk8
FROM openjdk:8-jre-alpine FROM openjdk:8-jre-alpine
# directory 생성
RUN mkdir -p /usr/app/config
# jar 파일이 복사되는 위치 # jar 파일이 복사되는 위치
ENV APP_HOME=/usr/app/ ENV APP_HOME=/usr/app/
# 작업 시작 위치 # 작업 시작 위치
@@ -9,5 +12,5 @@ WORKDIR $APP_HOME
COPY build/libs/*.jar config.jar COPY build/libs/*.jar config.jar
# application port # application port
EXPOSE 8888 EXPOSE 8888
# 실행 (ARG 아니고 ENV 값이다) # 실행
CMD ["java", "-Dspring.profiles.active=${profile:prod}", "-jar", "config.jar"] CMD ["java", "-Dsearch.location=/usr/app/config", "-jar", "config.jar"]

View File

@@ -5,12 +5,12 @@ spring:
application: application:
name: config-service name: config-service
profiles: profiles:
active: native,default # native file repository active: native # native file repository
cloud: cloud:
config: config:
server: server:
native: native:
search-locations: file:///${user.home}/workspace.edu/egovframe-msa-edu/config # Windows search-locations: ${search.location:file:///${user.home}/workspace.edu/egovframe-msa-edu/config} # Windows
# search-locations: file://${user.home}/workspace.edu/egovframe-msa-edu/config # MacOS # search-locations: file://${user.home}/workspace.edu/egovframe-msa-edu/config # MacOS
rabbitmq: rabbitmq:
host: localhost host: localhost

View File

@@ -8,14 +8,14 @@
</appender> </appender>
<!-- 로컬에서는 로그를 전송하지 않도록 설정 --> <!-- 로컬에서는 로그를 전송하지 않도록 설정 -->
<springProfile name="default"> <springProfile name="native">
<root level="INFO"> <root level="INFO">
<appender-ref ref="STDOUT" /> <appender-ref ref="STDOUT" />
</root> </root>
</springProfile> </springProfile>
<springProfile name="!default"> <springProfile name="!native">
<!-- java -Ddestination="localhost:5001" 와 같이 변경할 수 있다. cf 환경에서는 manifest.yml 파일에 환경변수로 추가 --> <!-- java -Dlogstash_hostname="localhost:5001" 와 같이 변경할 수 있다. cf 환경에서는 manifest.yml 파일에 환경변수로 추가 -->
<property name="destination" value="${destination:-localhost:5001}" /> <property name="destination" value="${logstash_hostname:-localhost:5001}" />
<property name="app_name" value="${app_name:-config-server}" /> <property name="app_name" value="${app_name:-config-server}" />
<!-- ELK - Logstash 로 로그를 전송하기 위한 appender --> <!-- ELK - Logstash 로 로그를 전송하기 위한 appender -->

View File

@@ -8,7 +8,7 @@ applications:
buildpack: java_buildpack # cf buildpacks 명령어로 java buildpack 이름 확인 buildpack: java_buildpack # cf buildpacks 명령어로 java buildpack 이름 확인
env: env:
spring_profiles_active: cf spring_profiles_active: cf
spring_cloud_config_uri: https://egov-config.paas-ta.org spring_cloud_config_uri: http://localhost:8888
eureka_server_enable_self_preservation: true eureka_server_enable_self_preservation: true
server_port: 80 server_port: 80
TZ: Asia/Seoul TZ: Asia/Seoul

View File

@@ -15,6 +15,6 @@ eureka:
register-with-eureka: false register-with-eureka: false
fetch-registry: false fetch-registry: false
service-url: service-url:
defaultZone: http://${spring.security.user.name}:${spring.security.user.password}@localhost:8761/eureka defaultZone: http://${spring.security.user.name}:${spring.security.user.password}@${eureka.instance.hostname:localhost}:8761/eureka
server: server:
peer-node-read-timeout-ms: 10000 peer-node-read-timeout-ms: 10000

View File

@@ -1,8 +1,8 @@
# openjdk8 base image # openjdk8 base image
FROM openjdk:8-jre-alpine FROM openjdk:8-jre-alpine
# config server uri: dockder run --e 로 변경 가능 # directory 생성
ENV SPRING_CLOUD_CONFIG_URI https://egov-config.paas-ta.org RUN mkdir -p /usr/app/msa-attach-volume/messages
# jar 파일이 복사되는 위치 # jar 파일이 복사되는 위치
ENV APP_HOME=/usr/app/ ENV APP_HOME=/usr/app/
# 작업 시작 위치 # 작업 시작 위치
@@ -11,5 +11,5 @@ WORKDIR $APP_HOME
COPY build/libs/*.jar app.jar COPY build/libs/*.jar app.jar
# application port # application port
#EXPOSE 8000 #EXPOSE 8000
# 실행 (application-cf.yml 프로필이 기본값) # 실행
CMD ["java", "-Dspring.profiles.active=${profile:cf}", "-jar", "app.jar"] CMD ["java", "-Dspring.profiles.active=${profile:default}", "-jar", "app.jar"]

View File

@@ -10,7 +10,7 @@ applications:
- egov-discovery-provided-service # discovery service binding - egov-discovery-provided-service # discovery service binding
env: env:
spring_profiles_active: cf spring_profiles_active: cf
spring_cloud_config_uri: https://egov-config.paas-ta.org spring_cloud_config_uri: http://localhost:8888
app_name: egov-portal-service # logstash custom app name app_name: egov-portal-service # logstash custom app name
TZ: Asia/Seoul TZ: Asia/Seoul
JAVA_OPTS: -Xss349k JAVA_OPTS: -Xss349k

View File

@@ -77,7 +77,6 @@ public class PolicyApiController {
*/ */
@PostMapping("/api/v1/policies") @PostMapping("/api/v1/policies")
public Long save(@RequestBody PolicySaveRequestDto saveRequestDto) { public Long save(@RequestBody PolicySaveRequestDto saveRequestDto) {
System.out.println(saveRequestDto.toString());
return policyService.save(saveRequestDto); return policyService.save(saveRequestDto);
} }

View File

@@ -428,8 +428,6 @@ public class AttachmentService extends AbstractService {
* @return * @return
*/ */
public String updateEntity(String attachmentCode, AttachmentUploadRequestDto uploadRequestDto) { public String updateEntity(String attachmentCode, AttachmentUploadRequestDto uploadRequestDto) {
System.out.println(" ====attachmentCode : " + attachmentCode);
System.out.println(" ====uploadRequestDto : " + uploadRequestDto);
List<Attachment> attachments = attachmentRepository.findByCode(attachmentCode); List<Attachment> attachments = attachmentRepository.findByCode(attachmentCode);
for (Attachment attachment : attachments) { for (Attachment attachment : attachments) {
attachment.updateEntity(uploadRequestDto.getEntityName(), uploadRequestDto.getEntityId()); attachment.updateEntity(uploadRequestDto.getEntityName(), uploadRequestDto.getEntityId());

View File

@@ -15,7 +15,7 @@
</springProfile> </springProfile>
<springProfile name="!default"> <springProfile name="!default">
<!-- java -Ddestination="localhost:5001" 와 같이 변경할 수 있다. cf 환경에서는 manifest.yml 파일에 환경변수로 추가 --> <!-- java -Ddestination="localhost:5001" 와 같이 변경할 수 있다. cf 환경에서는 manifest.yml 파일에 환경변수로 추가 -->
<property name="destination" value="${destination:-localhost:5001}" /> <property name="destination" value="${logstash_hostname:-localhost:5001}" />
<property name="app_name" value="${app_name:-portal-service}" /> <property name="app_name" value="${app_name:-portal-service}" />
<!-- ELK - Logstash 로 로그를 전송하기 위한 appender --> <!-- ELK - Logstash 로 로그를 전송하기 위한 appender -->

View File

@@ -10,6 +10,7 @@ import org.egovframe.cloud.portalservice.service.attachment.AttachmentService;
import org.egovframe.cloud.portalservice.util.RestResponsePage; import org.egovframe.cloud.portalservice.util.RestResponsePage;
import org.egovframe.cloud.portalservice.utils.FileStorageUtils; import org.egovframe.cloud.portalservice.utils.FileStorageUtils;
import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties;
@@ -36,6 +37,7 @@ import java.nio.file.Path;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Optional;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
@@ -70,6 +72,7 @@ class AttachmentApiControllerTest {
} }
} }
/** /**
* file to byte[] * file to byte[]
* *
@@ -169,16 +172,15 @@ class AttachmentApiControllerTest {
//given //given
String url = "/api/v1/upload/editor"; String url = "/api/v1/upload/editor";
Path testFile = Paths.get("/Users/violet/Desktop/test/300.jpg") Resource testFile = getTestFile();
.toAbsolutePath().normalize();
String base64data = Base64.toBase64String(getByteFile(testFile.toFile())); String base64data = Base64.toBase64String(getByteFile(testFile.getFile()));
AttachmentBase64RequestDto requestDto = AttachmentBase64RequestDto.builder() AttachmentBase64RequestDto requestDto = AttachmentBase64RequestDto.builder()
.fieldName("upload") .fieldName("upload")
.fileType("image/jpg") .fileType("text")
.fileBase64(base64data) .fileBase64(base64data)
.originalName("300.jpg") .originalName(testFile.getFilename())
.size(testFile.toFile().length()) .size(testFile.getFile().length())
.build(); .build();
@@ -186,7 +188,7 @@ class AttachmentApiControllerTest {
restTemplate.postForEntity(url, requestDto, AttachmentEditorResponseDto.class); restTemplate.postForEntity(url, requestDto, AttachmentEditorResponseDto.class);
assertThat(responseEntity.getStatusCode()).isEqualTo(HttpStatus.OK); assertThat(responseEntity.getStatusCode()).isEqualTo(HttpStatus.OK);
assertThat(responseEntity.getBody().getOriginalFileName()).isEqualTo("300.jpg"); assertThat(responseEntity.getBody().getOriginalFileName()).isEqualTo(testFile.getFilename());
} }
@Test @Test
@@ -239,16 +241,15 @@ class AttachmentApiControllerTest {
@Test @Test
public void 에디터이미지업로드_후_이미지태그에서_이미지파일_조회_정상() throws Exception { public void 에디터이미지업로드_후_이미지태그에서_이미지파일_조회_정상() throws Exception {
//given //given
Path testFile = Paths.get("/Users/violet/Desktop/test/300.jpg") Resource testFile = getTestFile();
.toAbsolutePath().normalize();
String base64data = Base64.toBase64String(getByteFile(testFile.toFile())); String base64data = Base64.toBase64String(getByteFile(testFile.getFile()));
AttachmentBase64RequestDto requestDto = AttachmentBase64RequestDto.builder() AttachmentBase64RequestDto requestDto = AttachmentBase64RequestDto.builder()
.fieldName("upload") .fieldName("upload")
.fileType("image/jpg") .fileType("text")
.fileBase64(base64data) .fileBase64(base64data)
.originalName("300.jpg") .originalName(testFile.getFilename())
.size(testFile.toFile().length()) .size(testFile.contentLength())
.build(); .build();
AttachmentEditorResponseDto responseDto = attachmentService.uploadEditor(requestDto); AttachmentEditorResponseDto responseDto = attachmentService.uploadEditor(requestDto);
@@ -266,7 +267,7 @@ class AttachmentApiControllerTest {
//given //given
List<AttachmentTempSaveRequestDto> saveRequestDtoList = getTempSaveDto(2); List<AttachmentTempSaveRequestDto> saveRequestDtoList = getTempSaveDto(2);
String url = "/api/v1/attachments/temp"; String url = "/api/v1/attachments/file";
//when //when
ResponseEntity<String> responseEntity = restTemplate.postForEntity(url, saveRequestDtoList, String.class); ResponseEntity<String> responseEntity = restTemplate.postForEntity(url, saveRequestDtoList, String.class);
@@ -324,7 +325,7 @@ class AttachmentApiControllerTest {
HttpEntity<List<AttachmentTempSaveRequestDto>> requestEntity = new HttpEntity<>(updateRequestDtoList); HttpEntity<List<AttachmentTempSaveRequestDto>> requestEntity = new HttpEntity<>(updateRequestDtoList);
//when //when
String url = "/api/v1/attachments/temp/"+attachmentCode; String url = "/api/v1/attachments/file/"+attachmentCode;
ResponseEntity<String> responseEntity = restTemplate.exchange(url, HttpMethod.PUT, requestEntity, String.class); ResponseEntity<String> responseEntity = restTemplate.exchange(url, HttpMethod.PUT, requestEntity, String.class);
@@ -341,7 +342,7 @@ class AttachmentApiControllerTest {
List<AttachmentTempSaveRequestDto> saveRequestDtoList2 = getTempSaveDto(3); List<AttachmentTempSaveRequestDto> saveRequestDtoList2 = getTempSaveDto(3);
attachmentService.save(saveRequestDtoList2); attachmentService.save(saveRequestDtoList2);
String url = "/api/v1/attachments/admin"; String url = "/api/v1/attachments";
//when //when
ResponseEntity<RestResponsePage<AttachmentResponseDto>> responseEntity = restTemplate.exchange( ResponseEntity<RestResponsePage<AttachmentResponseDto>> responseEntity = restTemplate.exchange(
@@ -370,7 +371,7 @@ class AttachmentApiControllerTest {
List<AttachmentTempSaveRequestDto> saveRequestDtoList2 = getTempSaveDto(3); List<AttachmentTempSaveRequestDto> saveRequestDtoList2 = getTempSaveDto(3);
String attachmentCode = attachmentService.save(saveRequestDtoList2); String attachmentCode = attachmentService.save(saveRequestDtoList2);
String url = "/api/v1/attachments/admin?keywordType=id&keyword="+attachmentCode; String url = "/api/v1/attachments?keywordType=id&keyword="+attachmentCode;
//when //when
ResponseEntity<RestResponsePage<AttachmentResponseDto>> responseEntity = restTemplate.exchange( ResponseEntity<RestResponsePage<AttachmentResponseDto>> responseEntity = restTemplate.exchange(
@@ -399,7 +400,7 @@ class AttachmentApiControllerTest {
List<AttachmentResponseDto> results = attachmentService.findByCode(attachmentCode); List<AttachmentResponseDto> results = attachmentService.findByCode(attachmentCode);
String uniqueId = results.get(1).getId(); String uniqueId = results.get(1).getId();
String url = "/api/v1/attachments/admin/"+uniqueId+"/true"; String url = "/api/v1/attachments/"+uniqueId+"/true";
//when //when
ResponseEntity<String> responseEntity = restTemplate.exchange(url, HttpMethod.PUT, null, String.class); ResponseEntity<String> responseEntity = restTemplate.exchange(url, HttpMethod.PUT, null, String.class);
@@ -407,10 +408,10 @@ class AttachmentApiControllerTest {
//then //then
assertThat(responseEntity.getStatusCode()).isEqualTo(HttpStatus.OK); assertThat(responseEntity.getStatusCode()).isEqualTo(HttpStatus.OK);
List<AttachmentResponseDto> saved = attachmentService.findByCode(attachmentCode); List<AttachmentResponseDto> saved = attachmentService.findByCode(attachmentCode);
AttachmentResponseDto updated = saved.stream() Optional<AttachmentResponseDto> any = saved.stream()
.filter(attachmentResponseDto -> attachmentResponseDto.getId().equals(uniqueId)) .filter(attachmentResponseDto -> attachmentResponseDto.getId().equals(uniqueId))
.findAny().get(); .findAny();
assertThat(updated.getIsDelete()).isTrue(); assertThat(any.isPresent()).isFalse();
} }
@Test @Test
@@ -420,7 +421,7 @@ class AttachmentApiControllerTest {
String attachmentCode = attachmentService.save(saveRequestDtoList2); String attachmentCode = attachmentService.save(saveRequestDtoList2);
List<AttachmentResponseDto> results = attachmentService.findByCode(attachmentCode); List<AttachmentResponseDto> results = attachmentService.findByCode(attachmentCode);
String url = "/api/v1/attachments/admin/"+results.get(1).getId(); String url = "/api/v1/attachments/"+results.get(1).getId();
//when //when
restTemplate.delete(url); restTemplate.delete(url);
@@ -487,7 +488,6 @@ class AttachmentApiControllerTest {
); );
} }
saveRequestDtoList.stream().forEach(System.out::println);
//2개 첨부파일 더하기 //2개 첨부파일 더하기
HttpHeaders headers = new HttpHeaders(); HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.MULTIPART_FORM_DATA); headers.setContentType(MediaType.MULTIPART_FORM_DATA);
@@ -557,24 +557,4 @@ class AttachmentApiControllerTest {
} }
//
// @Test
// public void 첨부파일_다운로드_정상() throws Exception {
// //given
// List<AttachmentSaveRequestDto> saveRequestDtoList2 = getTempSaveDto(1);
// String attachmentCode = attachmentService.save(saveRequestDtoList2);
//
// List<AttachmentResponseDto> byCode = attachmentService.findByCode(attachmentCode);
//
// String uniqueId = byCode.get(0).getUniqueId();
// String url = "/api/v1/download/"+uniqueId;
//
// //when
// ResponseEntity<ResponseEntity> responseEntity = restTemplate.getForEntity(url, ResponseEntity.class);
//
// //then
// re
//
// }
} }

View File

@@ -1,8 +1,6 @@
# openjdk8 base image # openjdk8 base image
FROM openjdk:8-jre-alpine FROM openjdk:8-jre-alpine
# config server uri: dockder run --e 로 변경 가능
ENV SPRING_CLOUD_CONFIG_URI https://egov-config.paas-ta.org
# jar 파일이 복사되는 위치 # jar 파일이 복사되는 위치
ENV APP_HOME=/usr/app/ ENV APP_HOME=/usr/app/
# 작업 시작 위치 # 작업 시작 위치

View File

@@ -10,7 +10,7 @@ applications:
- egov-discovery-provided-service # discovery service binding - egov-discovery-provided-service # discovery service binding
env: env:
spring_profiles_active: cf spring_profiles_active: cf
spring_cloud_config_uri: https://egov-config.paas-ta.org spring_cloud_config_uri: http://localhost:8888
app_name: egov-reserve-check-service # logstash custom app name app_name: egov-reserve-check-service # logstash custom app name
TZ: Asia/Seoul TZ: Asia/Seoul
JAVA_OPTS: -Xss349k JAVA_OPTS: -Xss349k

View File

@@ -1,36 +1,36 @@
package org.egovframe.cloud.reservechecksevice; package org.egovframe.cloud.reservechecksevice;
import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient; import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.ComponentScan;
import reactivefeign.spring.config.EnableReactiveFeignClients; import reactivefeign.spring.config.EnableReactiveFeignClients;
import reactor.blockhound.BlockHound; //import reactor.blockhound.BlockHound;
import java.security.Security; import java.security.Security;
@ComponentScan({"org.egovframe.cloud.common", "org.egovframe.cloud.reactive", "org.egovframe.cloud.reservechecksevice"}) // org.egovframe.cloud.common package 포함하기 위해 @ComponentScan({"org.egovframe.cloud.common", "org.egovframe.cloud.reactive", "org.egovframe.cloud.reservechecksevice"}) // org.egovframe.cloud.common package 포함하기 위해
@EnableDiscoveryClient @EnableDiscoveryClient
@EnableReactiveFeignClients @EnableReactiveFeignClients
@SpringBootApplication @SpringBootApplication
public class ReserveCheckSeviceApplication { public class ReserveCheckSeviceApplication {
public static void main(String[] args) { public static void main(String[] args) {
// TLSv1/v1.1 No longer works after upgrade, "No appropriate protocol" error // TLSv1/v1.1 No longer works after upgrade, "No appropriate protocol" error
String property = Security.getProperty("jdk.tls.disabledAlgorithms").replace(", TLSv1", "").replace(", TLSv1.1", ""); String property = Security.getProperty("jdk.tls.disabledAlgorithms").replace(", TLSv1", "").replace(", TLSv1.1", "");
Security.setProperty("jdk.tls.disabledAlgorithms", property); Security.setProperty("jdk.tls.disabledAlgorithms", property);
//blocking 코드 감지 //blocking 코드 감지
BlockHound.builder() // BlockHound.builder()
//mysql r2dbc 에서 호출되는 FileInputStream.readBytes() 가 블로킹코드인데 이를 허용해주도록 한다. // //mysql r2dbc 에서 호출되는 FileInputStream.readBytes() 가 블로킹코드인데 이를 허용해주도록 한다.
//해당 코드가 어디서 호출되는지 알지 못하는 상태에서 FileInputStream.readBytes() 자체를 허용해주는 것은 좋지 않다. // //해당 코드가 어디서 호출되는지 알지 못하는 상태에서 FileInputStream.readBytes() 자체를 허용해주는 것은 좋지 않다.
// 누군가 무분별하게 사용하게 되면 검출해 낼 수ㅂ 없어 시스템의 위험요소로 남게 된다. // // 누군가 무분별하게 사용하게 되면 검출해 낼 수ㅂ 없어 시스템의 위험요소로 남게 된다.
// r2dbc를 사용하기 위해 해당 호출부분만 허용하고 나머지는 여전히 검출대상으로 남기도록 한다. // // r2dbc를 사용하기 위해 해당 호출부분만 허용하고 나머지는 여전히 검출대상으로 남기도록 한다.
.allowBlockingCallsInside("dev.miku.r2dbc.mysql.client.ReactorNettyClient", "init") // .allowBlockingCallsInside("dev.miku.r2dbc.mysql.client.ReactorNettyClient", "init")
.install(); // .install();
SpringApplication.run(ReserveCheckSeviceApplication.class, args); SpringApplication.run(ReserveCheckSeviceApplication.class, args);
} }
} }

View File

@@ -1,17 +1,530 @@
package org.egovframe.cloud.reservechecksevice.api; package org.egovframe.cloud.reservechecksevice.api;
import static org.assertj.core.api.Assertions.*;
import static org.junit.jupiter.api.Assertions.*;
import java.time.LocalDateTime;
import org.egovframe.cloud.common.domain.Role;
import org.egovframe.cloud.common.exception.dto.ErrorCode;
import org.egovframe.cloud.common.exception.dto.ErrorResponse;
import org.egovframe.cloud.reservechecksevice.api.reserve.dto.ReserveCancelRequestDto;
import org.egovframe.cloud.reservechecksevice.api.reserve.dto.ReserveListResponseDto;
import org.egovframe.cloud.reservechecksevice.api.reserve.dto.ReserveSaveRequestDto;
import org.egovframe.cloud.reservechecksevice.api.reserve.dto.ReserveUpdateRequestDto;
import org.egovframe.cloud.reservechecksevice.client.ReserveItemServiceClient;
import org.egovframe.cloud.reservechecksevice.client.UserServiceClient;
import org.egovframe.cloud.reservechecksevice.client.dto.ReserveItemRelationResponseDto;
import org.egovframe.cloud.reservechecksevice.client.dto.ReserveItemResponseDto;
import org.egovframe.cloud.reservechecksevice.client.dto.UserResponseDto;
import org.egovframe.cloud.reservechecksevice.domain.location.Location;
import org.egovframe.cloud.reservechecksevice.domain.reserve.Reserve;
import org.egovframe.cloud.reservechecksevice.domain.reserve.ReserveItem;
import org.egovframe.cloud.reservechecksevice.domain.reserve.ReserveRepository;
import org.egovframe.cloud.reservechecksevice.domain.reserve.ReserveStatus;
import org.egovframe.cloud.reservechecksevice.util.RestResponsePage;
import org.egovframe.cloud.reservechecksevice.util.WithCustomMockUser;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.ArgumentMatchers;
import org.mockito.BDDMockito;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.test.context.ActiveProfiles; import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.TestPropertySource; import org.springframework.test.context.TestPropertySource;
import org.springframework.test.web.reactive.server.WebTestClient;
import reactor.core.publisher.Mono;
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@EnableConfigurationProperties @EnableConfigurationProperties
@TestPropertySource(properties = {"spring.config.location=classpath:application-test.yml"}) @TestPropertySource(properties = {"spring.config.location=classpath:application-test.yml"})
@ActiveProfiles(profiles = "test") @ActiveProfiles(profiles = "test")
class ReserveApiControllerTest { public class ReserveApiControllerTest {
@Autowired
private ReserveRepository reserveRepository;
@MockBean
private ReserveItemServiceClient reserveItemServiceClient;
@MockBean
private UserServiceClient userServiceClient;
} @Autowired
private WebTestClient webTestClient;
private static final String API_URL = "/api/v1/reserves";
private UserResponseDto user;
private Location location;
private ReserveItem reserveItem;
private Reserve reserve;
@BeforeEach
public void setup() {
user = UserResponseDto.builder()
.roleId(Role.ADMIN.getKey())
.userId("user")
.build();
location = Location.builder()
.locationId(1L)
.locationName("location")
.build();
reserveItem = ReserveItem.builder()
.reserveItemId(1L)
.reserveItemName("test")
.locationId(location.getLocationId())
.location(location)
.categoryId("place")
.inventoryQty(100)
.totalQty(100)
.reserveMethodId("internet")
.reserveMeansId("realtime")
.requestStartDate(LocalDateTime.of(2021, 1, 1, 1, 1))
.requestEndDate(LocalDateTime.of(2021, 12, 31, 23, 59))
.operationStartDate(LocalDateTime.of(2021, 1, 1, 1, 1))
.operationEndDate(LocalDateTime.of(2021, 12, 31, 23, 59))
.build();
reserve = Reserve.builder()
.reserveId("1")
.reserveItemId(reserveItem.getReserveItemId())
.reserveQty(50)
.reservePurposeContent("test")
.reserveStatusId("request")
.reserveStartDate(LocalDateTime.of(2021, 9, 9, 1, 1))
.reserveEndDate(LocalDateTime.of(2021, 9, 20, 1, 1))
.userId(user.getUserId())
.userEmail("user@email.com")
.userContactNo("contact")
.build();
reserve.setReserveItem(reserveItem);
reserve.setUser(user);
}
@AfterEach
public void tearDown() {
reserveRepository.deleteAll().block();
}
@Test
public void 예약신청관리_목록_조회_성공() throws Exception {
//given
BDDMockito.when(userServiceClient.findByUserId(ArgumentMatchers.anyString()))
.thenReturn(Mono.just(user));
BDDMockito.when(reserveItemServiceClient.findByIdWithRelations(ArgumentMatchers.anyLong()))
.thenReturn(Mono.just(ReserveItemRelationResponseDto.builder().entity(reserveItem).build()));
Reserve saved = reserveRepository.insert(reserve).block();
assertNotNull(saved);
//when
webTestClient.get()
.uri(API_URL + "?page=0&size=5")
.exchange()
.expectStatus().isOk()
.expectBody(new ParameterizedTypeReference<RestResponsePage<ReserveListResponseDto>>() {
})
.value(page -> {
//then
assertThat(page.getTotalElements()).isEqualTo(1L);
assertThat(page.getContent().get(0).getReserveId()).isEqualTo(reserve.getReserveId());
page.getContent().stream().forEach(System.out::println);
});
}
@Test
@WithCustomMockUser(userId = "admin", role = Role.ADMIN)
public void 관리자_취소_성공() throws Exception {
BDDMockito.when(reserveItemServiceClient.updateInventory(ArgumentMatchers.anyLong(), ArgumentMatchers.anyInt()))
.thenReturn(Mono.just(true));
Reserve saved = reserveRepository.insert(reserve).block();
assertNotNull(saved);
webTestClient.put()
.uri(API_URL + "/cancel/{reserveId}", saved.getReserveId())
.bodyValue(ReserveCancelRequestDto.builder().reasonCancelContent("reason for cancellation").build())
.exchange()
.expectStatus().isNoContent();
Reserve updated = reserveRepository.findById(saved.getReserveId()).block();
assertThat(updated.getReserveStatusId()).isEqualTo("cancel");
assertThat(updated.getReasonCancelContent()).isEqualTo("reason for cancellation");
}
@Test
@WithCustomMockUser(userId = "user", role = Role.USER)
public void 사용자_취소_성공() {
//given
BDDMockito.when(reserveItemServiceClient.updateInventory(ArgumentMatchers.anyLong(), ArgumentMatchers.anyInt()))
.thenReturn(Mono.just(true));
Reserve saved = reserveRepository.insert(reserve).block();
assertNotNull(saved);
//when
webTestClient.put()
.uri(API_URL + "/cancel/{reserveId}", saved.getReserveId())
.bodyValue(ReserveCancelRequestDto.builder().reasonCancelContent("reason for cancellation").build())
.exchange()
.expectStatus().isNoContent()
;
Reserve updated = reserveRepository.findById(saved.getReserveId()).block();
assertThat(updated.getReserveStatusId()).isEqualTo("cancel");
assertThat(updated.getReasonCancelContent()).isEqualTo("reason for cancellation");
}
@Test
@WithCustomMockUser(userId = "test", role = Role.USER)
public void 다른사용자_예약_취소_실패() throws Exception {
BDDMockito.when(reserveItemServiceClient.updateInventory(ArgumentMatchers.anyLong(), ArgumentMatchers.anyInt()))
.thenReturn(Mono.just(true));
Reserve saved = reserveRepository.insert(reserve).block();
assertNotNull(saved);
webTestClient.put()
.uri(API_URL + "/cancel/{reserveId}", saved.getReserveId())
.bodyValue(ReserveCancelRequestDto.builder().reasonCancelContent("reason for cancellation").build())
.exchange()
.expectStatus().isBadRequest()
.expectBody(ErrorResponse.class)
.value(response -> {
assertThat(response.getMessage()).isEqualTo("해당 예약은 취소할 수 없습니다.");
assertThat(response.getCode()).isEqualTo(ErrorCode.BUSINESS_CUSTOM_MESSAGE.getCode());
});
}
@Test
@WithCustomMockUser(userId = "user", role = Role.USER)
public void 예약상태_완료_취소_실패() throws Exception {
Reserve done = reserve.updateStatus(ReserveStatus.DONE.getKey());
Reserve saved = reserveRepository.insert(done).block();
assertNotNull(saved);
BDDMockito.when(reserveItemServiceClient.updateInventory(ArgumentMatchers.anyLong(), ArgumentMatchers.anyInt()))
.thenReturn(Mono.just(true));
webTestClient.put()
.uri(API_URL + "/cancel/{reserveId}", saved.getReserveId())
.bodyValue(ReserveCancelRequestDto.builder().reasonCancelContent("reason for cancellation").build())
.exchange()
.expectBody(ErrorResponse.class)
.value(response -> {
assertThat(response.getMessage()).isEqualTo("해당 예약은 이미 실행되어 취소할 수 없습니다.");
assertThat(response.getCode()).isEqualTo(ErrorCode.BUSINESS_CUSTOM_MESSAGE.getCode());
});
;
}
@Test
@WithCustomMockUser(userId = "user", role = Role.USER)
public void 관리자가_아닌_경우_승인_실패() throws Exception {
Reserve saved = reserveRepository.insert(reserve).block();
assertNotNull(saved);
BDDMockito.when(reserveItemServiceClient.findById(ArgumentMatchers.anyLong()))
.thenReturn(Mono.just(ReserveItemResponseDto.builder().reserveItem(reserveItem).build()));
BDDMockito.when(reserveItemServiceClient.updateInventory(ArgumentMatchers.anyLong(), ArgumentMatchers.anyInt()))
.thenReturn(Mono.just(true));
webTestClient.put()
.uri(API_URL + "/approve/{reserveId}", saved.getReserveId())
.exchange()
.expectStatus().isBadRequest()
.expectBody(ErrorResponse.class)
.value(response -> {
assertThat(response.getMessage()).isEqualTo("관리자만 승인할 수 있습니다.");
});
}
@Test
@WithCustomMockUser(userId = "admin", role = Role.ADMIN)
public void 예약승인_성공() throws Exception {
Reserve saved = reserveRepository.insert(reserve).block();
assertNotNull(saved);
BDDMockito.when(reserveItemServiceClient.findById(ArgumentMatchers.anyLong()))
.thenReturn(Mono.just(ReserveItemResponseDto.builder().reserveItem(reserveItem).build()));
BDDMockito.when(reserveItemServiceClient.updateInventory(ArgumentMatchers.anyLong(), ArgumentMatchers.anyInt()))
.thenReturn(Mono.just(true));
webTestClient.put()
.uri(API_URL + "/approve/{reserveId}", saved.getReserveId())
.exchange()
.expectStatus().isNoContent();
Reserve updated = reserveRepository.findById(saved.getReserveId()).block();
assertThat(updated.getReserveStatusId()).isEqualTo("approve");
}
@Test
@WithCustomMockUser(userId = "admin", role = Role.ADMIN)
public void 예약승인_실패_재고부족() throws Exception {
ReserveItem failReserveItem = ReserveItem.builder()
.reserveItemId(1L)
.reserveItemName("test")
.locationId(location.getLocationId())
.location(location)
.categoryId("equipment")
.totalQty(20)
.inventoryQty(10)
.reserveMethodId("internet")
.reserveMeansId("realtime")
.isPeriod(false)
.requestStartDate(LocalDateTime.of(2021, 1, 1, 1, 1))
.requestEndDate(LocalDateTime.of(2021, 12, 31, 23, 59))
.operationStartDate(LocalDateTime.of(2021, 1, 1, 1, 1))
.operationEndDate(LocalDateTime.of(2021, 12, 31, 23, 59))
.build();
Reserve saved = reserveRepository.insert(reserve).block();
assertNotNull(saved);
BDDMockito.when(reserveItemServiceClient.findById(ArgumentMatchers.anyLong()))
.thenReturn(Mono.just(ReserveItemResponseDto.builder().reserveItem(failReserveItem).build()));
BDDMockito.when(reserveItemServiceClient.updateInventory(ArgumentMatchers.anyLong(), ArgumentMatchers.anyInt()))
.thenReturn(Mono.just(false));
webTestClient.put()
.uri(API_URL + "/approve/{reserveId}", saved.getReserveId())
.exchange()
.expectStatus().isBadRequest()
.expectBody(ErrorResponse.class)
.value(response -> {
assertThat(response.getMessage()).isEqualTo("해당 날짜에 예약할 수 있는 재고수량이 없습니다.");
});
}
@Test
@WithCustomMockUser(userId = "admin", role = Role.ADMIN)
public void 관리자_예약정보_수정_성공() throws Exception {
Reserve saved = reserveRepository.insert(reserve).block();
assertNotNull(saved);
BDDMockito.when(reserveItemServiceClient.findById(ArgumentMatchers.anyLong()))
.thenReturn(Mono.just(ReserveItemResponseDto.builder().reserveItem(reserveItem).build()));
BDDMockito.when(reserveItemServiceClient.updateInventory(ArgumentMatchers.anyLong(), ArgumentMatchers.anyInt()))
.thenReturn(Mono.just(true));
ReserveUpdateRequestDto updateRequestDto =
ReserveUpdateRequestDto.builder()
.reserveItemId(saved.getReserveItemId())
.categoryId(saved.getReserveItem().getCategoryId())
.reservePurposeContent("purpose")
.reserveQty(10)
.reserveStartDate(saved.getReserveStartDate())
.reserveEndDate(saved.getReserveEndDate())
.attachmentCode(saved.getAttachmentCode())
.userId(saved.getUserId())
.userContactNo("contact update")
.userEmail(saved.getUserEmail())
.build();
webTestClient.put()
.uri(API_URL + "/{reserveId}", saved.getReserveId())
.bodyValue(updateRequestDto)
.exchange()
.expectStatus().isNoContent()
;
Reserve updated = reserveRepository.findById(saved.getReserveId()).block();
assertThat(updated.getReservePurposeContent()).isEqualTo("purpose");
assertThat(updated.getReserveQty()).isEqualTo(10);
assertThat(updated.getUserContactNo()).isEqualTo("contact update");
}
@Test
@WithCustomMockUser(userId = "test", role = Role.USER)
public void 다른사용자_예약정보_수정_실패() throws Exception {
Reserve saved = reserveRepository.insert(reserve).block();
assertNotNull(saved);
BDDMockito.when(reserveItemServiceClient.findById(ArgumentMatchers.anyLong()))
.thenReturn(Mono.just(ReserveItemResponseDto.builder().reserveItem(reserveItem).build()));
BDDMockito.when(reserveItemServiceClient.updateInventory(ArgumentMatchers.anyLong(), ArgumentMatchers.anyInt()))
.thenReturn(Mono.just(true));
ReserveUpdateRequestDto updateRequestDto =
ReserveUpdateRequestDto.builder()
.reserveItemId(saved.getReserveItemId())
.categoryId(saved.getReserveItem().getCategoryId())
.reservePurposeContent("purpose")
.reserveQty(10)
.reserveStartDate(saved.getReserveStartDate())
.reserveEndDate(saved.getReserveEndDate())
.attachmentCode(saved.getAttachmentCode())
.userId(saved.getUserId())
.userContactNo("contact update")
.userEmail(saved.getUserEmail())
.build();
webTestClient.put()
.uri(API_URL + "/{reserveId}", saved.getReserveId())
.bodyValue(updateRequestDto)
.exchange()
.expectStatus().isBadRequest()
.expectBody(ErrorResponse.class)
.value(response -> {
assertThat(response.getMessage()).isEqualTo("해당 예약은 수정할 수 없습니다.");
});
}
@Test
@WithCustomMockUser(userId = "user", role = Role.USER)
public void 사용자_예약정보_수정_성공() throws Exception {
Reserve saved = reserveRepository.insert(reserve).block();
assertNotNull(saved);
BDDMockito.when(reserveItemServiceClient.findById(ArgumentMatchers.anyLong()))
.thenReturn(Mono.just(ReserveItemResponseDto.builder().reserveItem(reserveItem).build()));
BDDMockito.when(reserveItemServiceClient.updateInventory(ArgumentMatchers.anyLong(), ArgumentMatchers.anyInt()))
.thenReturn(Mono.just(true));
ReserveUpdateRequestDto updateRequestDto =
ReserveUpdateRequestDto.builder()
.reserveItemId(saved.getReserveItemId())
.categoryId(saved.getReserveItem().getCategoryId())
.reservePurposeContent("purpose")
.reserveQty(10)
.reserveStartDate(saved.getReserveStartDate())
.reserveEndDate(saved.getReserveEndDate())
.attachmentCode(saved.getAttachmentCode())
.userId(saved.getUserId())
.userContactNo("contact update")
.userEmail(saved.getUserEmail())
.build();
webTestClient.put()
.uri(API_URL + "/{reserveId}", saved.getReserveId())
.bodyValue(updateRequestDto)
.exchange()
.expectStatus().isNoContent()
;
Reserve updated = reserveRepository.findById(saved.getReserveId()).block();
assertThat(updated.getReservePurposeContent()).isEqualTo("purpose");
assertThat(updated.getReserveQty()).isEqualTo(10);
assertThat(updated.getUserContactNo()).isEqualTo("contact update");
}
@Test
@WithCustomMockUser(userId = "user", role = Role.USER)
public void 사용자_상태승인인예약정보_수정_실패() throws Exception {
Reserve failedReserve = reserve.withReserveStatusId(ReserveStatus.APPROVE.getKey());
Reserve saved = reserveRepository.insert(failedReserve).block();
assertNotNull(saved);
BDDMockito.when(reserveItemServiceClient.findById(ArgumentMatchers.anyLong()))
.thenReturn(Mono.just(ReserveItemResponseDto.builder().reserveItem(reserveItem).build()));
BDDMockito.when(reserveItemServiceClient.updateInventory(ArgumentMatchers.anyLong(), ArgumentMatchers.anyInt()))
.thenReturn(Mono.just(false));
ReserveUpdateRequestDto updateRequestDto =
ReserveUpdateRequestDto.builder()
.reserveItemId(saved.getReserveItemId())
.categoryId(saved.getReserveItem().getCategoryId())
.reservePurposeContent("purpose")
.reserveQty(10)
.reserveStartDate(saved.getReserveStartDate())
.reserveEndDate(saved.getReserveEndDate())
.attachmentCode(saved.getAttachmentCode())
.userId(saved.getUserId())
.userContactNo("contact update")
.userEmail(saved.getUserEmail())
.build();
webTestClient.put()
.uri(API_URL + "/{reserveId}", saved.getReserveId())
.bodyValue(updateRequestDto)
.exchange()
.expectStatus().isBadRequest()
.expectBody(ErrorResponse.class)
.value(response -> {
assertThat(response.getMessage()).isEqualTo("예약 신청 상태인 경우에만 수정 가능합니다.");
});
}
@Test
public void 관리자_예약_성공() throws Exception {
BDDMockito.when(reserveItemServiceClient.findById(ArgumentMatchers.anyLong()))
.thenReturn(Mono.just(ReserveItemResponseDto.builder().reserveItem(reserveItem).build()));
BDDMockito.when(reserveItemServiceClient.updateInventory(ArgumentMatchers.anyLong(), ArgumentMatchers.anyInt()))
.thenReturn(Mono.just(true));
ReserveSaveRequestDto saveRequestDto =
ReserveSaveRequestDto.builder()
.reserveItemId(reserve.getReserveItemId())
.categoryId(reserve.getReserveItem().getCategoryId())
.reservePurposeContent(reserve.getReservePurposeContent())
.reserveQty(reserve.getReserveQty())
.reserveStartDate(reserve.getReserveStartDate())
.reserveEndDate(reserve.getReserveEndDate())
.attachmentCode(reserve.getAttachmentCode())
.userId(reserve.getUserId())
.userContactNo(reserve.getUserContactNo())
.userEmail(reserve.getUserEmail())
.build();
webTestClient.post()
.uri(API_URL)
.bodyValue(saveRequestDto)
.exchange()
.expectStatus().isCreated();
Reserve saved = reserveRepository.findById(reserve.getReserveId()).block();
System.out.println(saved);
}
@Test
public void 예약신청_valid_실패() throws Exception {
ReserveItem validReserveItem = ReserveItem.builder()
.reserveItemId(1L)
.reserveItemName("test")
.locationId(location.getLocationId())
.location(location)
.categoryId("equipment")
.totalQty(100)
.inventoryQty(10)
.operationStartDate(LocalDateTime.of(2021, 10, 1, 1, 1))
.operationEndDate(LocalDateTime.of(2021, 10, 31, 23, 59))
.build();
reserve.setReserveItem(validReserveItem);
ReserveSaveRequestDto saveRequestDto =
ReserveSaveRequestDto.builder()
.reserveItemId(reserve.getReserveItemId())
.categoryId(reserve.getReserveItem().getCategoryId())
.reservePurposeContent(reserve.getReservePurposeContent())
.reserveQty(null)
.reserveStartDate(LocalDateTime.of(2021, 11, 1, 1, 1))
.reserveEndDate(reserve.getReserveEndDate())
.attachmentCode(reserve.getAttachmentCode())
.userId(reserve.getUserId())
.userContactNo(reserve.getUserContactNo())
.userEmail(reserve.getUserEmail())
.build();
webTestClient.post()
.uri(API_URL)
.bodyValue(saveRequestDto)
.exchange()
.expectStatus().isBadRequest()
;
}
}

View File

@@ -1,9 +1,5 @@
package org.egovframe.cloud.reservechecksevice.config; package org.egovframe.cloud.reservechecksevice.config;
import io.r2dbc.h2.H2ConnectionConfiguration;
import io.r2dbc.h2.H2ConnectionFactory;
import io.r2dbc.h2.H2ConnectionOption;
import io.r2dbc.spi.ConnectionFactory;
import org.springframework.boot.test.context.TestConfiguration; import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Profile; import org.springframework.context.annotation.Profile;
@@ -13,6 +9,11 @@ import org.springframework.r2dbc.connection.init.CompositeDatabasePopulator;
import org.springframework.r2dbc.connection.init.ConnectionFactoryInitializer; import org.springframework.r2dbc.connection.init.ConnectionFactoryInitializer;
import org.springframework.r2dbc.connection.init.ResourceDatabasePopulator; import org.springframework.r2dbc.connection.init.ResourceDatabasePopulator;
import io.r2dbc.h2.H2ConnectionConfiguration;
import io.r2dbc.h2.H2ConnectionFactory;
import io.r2dbc.h2.H2ConnectionOption;
import io.r2dbc.spi.ConnectionFactory;
@Profile("test") @Profile("test")
@TestConfiguration @TestConfiguration
@EnableR2dbcRepositories @EnableR2dbcRepositories
@@ -20,7 +21,7 @@ public class R2dbcConfig {
@Bean @Bean
public H2ConnectionFactory connectionFactory() { public H2ConnectionFactory connectionFactory() {
return new H2ConnectionFactory(H2ConnectionConfiguration.builder() return new H2ConnectionFactory(H2ConnectionConfiguration.builder()
.tcp("localhost", "~/querydsl") .inMemory("testdb")
.property(H2ConnectionOption.DB_CLOSE_DELAY, "-1") .property(H2ConnectionOption.DB_CLOSE_DELAY, "-1")
.username("sa") .username("sa")
.build()); .build());

View File

@@ -1,14 +1,15 @@
package org.egovframe.cloud.reservechecksevice.util; package org.egovframe.cloud.reservechecksevice.util;
import com.fasterxml.jackson.annotation.JsonCreator; import java.util.Collections;
import com.fasterxml.jackson.annotation.JsonProperty; import java.util.List;
import com.fasterxml.jackson.databind.JsonNode;
import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Pageable;
import java.util.Collections; import com.fasterxml.jackson.annotation.JsonCreator;
import java.util.List; import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.JsonNode;
/** /**
* org.egovframe.cloud.boardservice.util.RestResponsePage * org.egovframe.cloud.boardservice.util.RestResponsePage

View File

@@ -1,11 +1,11 @@
package org.egovframe.cloud.reservechecksevice.util; package org.egovframe.cloud.reservechecksevice.util;
import org.egovframe.cloud.common.domain.Role;
import org.springframework.security.test.context.support.WithSecurityContext;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
import org.egovframe.cloud.common.domain.Role;
import org.springframework.security.test.context.support.WithSecurityContext;
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
@WithSecurityContext(factory = WithMockCustomUserSecurityContextFactory.class) @WithSecurityContext(factory = WithMockCustomUserSecurityContextFactory.class)
public @interface WithCustomMockUser { public @interface WithCustomMockUser {

View File

@@ -1,14 +1,14 @@
package org.egovframe.cloud.reservechecksevice.util; package org.egovframe.cloud.reservechecksevice.util;
import java.util.ArrayList;
import java.util.List;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContext; import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.test.context.support.WithSecurityContextFactory; import org.springframework.security.test.context.support.WithSecurityContextFactory;
import java.util.ArrayList;
import java.util.List;
public class WithMockCustomUserSecurityContextFactory implements WithSecurityContextFactory<WithCustomMockUser> { public class WithMockCustomUserSecurityContextFactory implements WithSecurityContextFactory<WithCustomMockUser> {
@Override @Override

View File

@@ -2,20 +2,6 @@ spring:
application: application:
name: reserve-check-service name: reserve-check-service
datasource:
url: jdbc:h2:mem:testdb;MODE=MYSQL;DB_CLOSE_DELAY=-1;DATABASE_TO_UPPER=false
username: sa
password:
driver-class-name: org.h2.Driver
jpa:
hibernate:
generate-ddl: true
ddl-auto: create-drop
properties:
hibernate:
format_sql: true
default_batch_fetch_size: 1000
show-sql: true
h2: h2:
console: console:
enabled: true enabled: true

View File

@@ -1,72 +1,17 @@
-- location Table Create SQL
CREATE TABLE IF NOT EXISTS location
(
location_id BIGINT NOT NULL AUTO_INCREMENT COMMENT '지역 id',
location_name VARCHAR(200) NULL COMMENT '지역 이름',
sort_seq SMALLINT(3) NULL COMMENT '정렬 순서',
use_at TINYINT(1) NULL DEFAULT 1 COMMENT '사용 여부',
created_by VARCHAR(255) NULL COMMENT '생성자',
create_date DATETIME NULL COMMENT '생성일',
last_modified_by VARCHAR(255) NULL COMMENT '수정자',
modified_date DATETIME NULL COMMENT '수정일',
PRIMARY KEY (location_id)
) ;
-- reserve_item Table Create SQL
CREATE TABLE IF NOT EXISTS reserve_item
(
reserve_item_id BIGINT NOT NULL AUTO_INCREMENT COMMENT '예약 물품 id',
reserve_item_name VARCHAR(200) NULL COMMENT '예약 물품 이름',
location_id BIGINT NULL COMMENT '지역 id',
category_id VARCHAR(20) NULL COMMENT '예약유형 - 공통코드 reserve-category',
total_qty BIGINT(18) NULL COMMENT '총 재고/수용인원 수',
inventory_qty BIGINT(18) NULL COMMENT '현재 남은 재고/수용인원 수',
operation_start_date DATETIME NULL COMMENT '운영 시작 일',
operation_end_date DATETIME NULL COMMENT '운영 종료 일',
reserve_method_id VARCHAR(20) NULL COMMENT '예약 방법 - 공통코드 reserve-method',
reserve_means_id VARCHAR(20) NULL COMMENT '예약 구분 (인터넷 예약 시) - 공통코드 reserve-means',
request_start_date DATETIME NULL COMMENT '예약 신청 시작 일시',
request_end_date DATETIME NULL COMMENT '예약 신청 종료 일시',
period_at TINYINT(1) NULL DEFAULT 0 COMMENT '기간 지정 가능 여부 - true: 지정 가능, false: 지정 불가',
period_max_count SMALLINT(3) NULL COMMENT '최대 예약 가능 일 수',
external_url VARCHAR(500) NULL COMMENT '외부링크',
selection_means_id VARCHAR(20) NULL COMMENT '선별 방법 - 공통코드 reserve-selection-means',
free_at TINYINT(1) NULL DEFAULT 1 COMMENT '유/무료 - true: 무료, false: 유료',
usage_cost DECIMAL(18, 0) NULL COMMENT '이용 요금',
use_at TINYINT(1) NULL DEFAULT 1 COMMENT '사용 여부',
purpose_content VARCHAR(4000) NULL COMMENT '용도',
item_addr VARCHAR(500) NULL COMMENT '주소',
target_id VARCHAR(20) NULL COMMENT '이용 대상 - 공통코드 reserve-target',
excluded_content VARCHAR(2000) NULL COMMENT '사용허가 제외대상',
homepage_url VARCHAR(500) NULL COMMENT '홈페이지 url',
contact_no VARCHAR(50) NULL COMMENT '문의처',
manager_dept_name VARCHAR(200) NULL COMMENT '담당자 소속',
manager_name VARCHAR(200) NULL COMMENT '담당자 이름',
manager_contact_no VARCHAR(50) NULL COMMENT '담당자 연락처',
create_date DATETIME NULL COMMENT '생성일',
created_by VARCHAR(255) NULL COMMENT '생성자',
modified_date DATETIME NULL COMMENT '수정일',
last_modified_by VARCHAR(255) NULL COMMENT '수정자',
PRIMARY KEY (reserve_item_id),
CONSTRAINT FK_reserve_item_location_id FOREIGN KEY (location_id)
REFERENCES location (location_id) ON DELETE RESTRICT ON UPDATE RESTRICT
) ;
-- reserve Table Create SQL -- reserve Table Create SQL
CREATE TABLE IF NOT EXISTS reserve CREATE TABLE IF NOT EXISTS reserve
( (
reserve_id BIGINT NOT NULL AUTO_INCREMENT COMMENT '예약 id', reserve_id VARCHAR(255) NOT NULL COMMENT '예약 id',
reserve_item_id BIGINT NULL COMMENT '예약 물품 id', reserve_item_id BIGINT NULL COMMENT '예약 물품 id',
location_id BIGINT NULL COMMENT '예약 물품-지역 id',
category_id VARCHAR(255) NULL COMMENT '예약 물품-유형 id',
reserve_qty BIGINT(18) NULL COMMENT '예약 신청인원/수량', reserve_qty BIGINT(18) NULL COMMENT '예약 신청인원/수량',
reserve_purpose_content VARCHAR(4000) NULL COMMENT '예약신청 목적', reserve_purpose_content VARCHAR(4000) NULL COMMENT '예약신청 목적',
attachment_code VARCHAR(255) NULL COMMENT '첨부파일 코드', attachment_code VARCHAR(255) NULL COMMENT '첨부파일 코드',
reserve_start_date DATETIME NULL COMMENT '예약 신청 시작일', reserve_start_date DATETIME NULL COMMENT '예약 신청 시작일',
reserve_end_date DATETIME NULL COMMENT '예약 신청 종료일', reserve_end_date DATETIME NULL COMMENT '예약 신청 종료일',
reserve_status_id VARCHAR(20) NULL COMMENT '예약상태 - 공통코드(reserve-status)', reserve_status_id VARCHAR(20) NULL COMMENT '예약상태 - 공통코드(reserve-status)',
reason_cancel_content VARCHAR(4000) NULL COMMENT '예약 취소 사유',
user_id VARCHAR(255) NULL COMMENT '예약자 id', user_id VARCHAR(255) NULL COMMENT '예약자 id',
user_contact_no VARCHAR(50) NULL COMMENT '예약자 연락처', user_contact_no VARCHAR(50) NULL COMMENT '예약자 연락처',
user_email_addr VARCHAR(500) NULL COMMENT '예약자 이메일', user_email_addr VARCHAR(500) NULL COMMENT '예약자 이메일',
@@ -74,8 +19,5 @@ CREATE TABLE IF NOT EXISTS reserve
created_by VARCHAR(255) NULL COMMENT '생성자', created_by VARCHAR(255) NULL COMMENT '생성자',
modified_date DATETIME NULL COMMENT '수정일', modified_date DATETIME NULL COMMENT '수정일',
last_modified_by VARCHAR(255) NULL COMMENT '수정자', last_modified_by VARCHAR(255) NULL COMMENT '수정자',
PRIMARY KEY (reserve_id), PRIMARY KEY (reserve_id)
CONSTRAINT FK_reserve_reserve_item_id FOREIGN KEY (reserve_item_id)
REFERENCES reserve_item (reserve_item_id) ON DELETE RESTRICT ON UPDATE RESTRICT
) ; ) ;

View File

@@ -1,8 +1,6 @@
# openjdk8 base image # openjdk8 base image
FROM openjdk:8-jre-alpine FROM openjdk:8-jre-alpine
# config server uri: dockder run --e 로 변경 가능
ENV SPRING_CLOUD_CONFIG_URI https://egov-config.paas-ta.org
# jar 파일이 복사되는 위치 # jar 파일이 복사되는 위치
ENV APP_HOME=/usr/app/ ENV APP_HOME=/usr/app/
# 작업 시작 위치 # 작업 시작 위치

View File

@@ -10,7 +10,7 @@ applications:
- egov-discovery-provided-service # discovery service binding - egov-discovery-provided-service # discovery service binding
env: env:
spring_profiles_active: cf spring_profiles_active: cf
spring_cloud_config_uri: https://egov-config.paas-ta.org spring_cloud_config_uri: http://localhost:8888
app_name: egov-reserve-item-service # logstash custom app name app_name: egov-reserve-item-service # logstash custom app name
TZ: Asia/Seoul TZ: Asia/Seoul
JAVA_OPTS: -Xss349k JAVA_OPTS: -Xss349k

View File

@@ -1,40 +1,40 @@
package org.egovframe.cloud.reserveitemservice; package org.egovframe.cloud.reserveitemservice;
import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient; import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients; import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.ComponentScan;
import reactivefeign.spring.config.EnableReactiveFeignClients; import reactivefeign.spring.config.EnableReactiveFeignClients;
import reactor.blockhound.BlockHound; //import reactor.blockhound.BlockHound;
import java.security.Security; import java.security.Security;
@ComponentScan({"org.egovframe.cloud.common", "org.egovframe.cloud.reactive", "org.egovframe.cloud.reserveitemservice"}) // org.egovframe.cloud.common package 포함하기 위해 @ComponentScan({"org.egovframe.cloud.common", "org.egovframe.cloud.reactive", "org.egovframe.cloud.reserveitemservice"}) // org.egovframe.cloud.common package 포함하기 위해
@EnableDiscoveryClient @EnableDiscoveryClient
@EnableReactiveFeignClients @EnableReactiveFeignClients
@SpringBootApplication @SpringBootApplication
public class ReserveItemServiceApplication { public class ReserveItemServiceApplication {
public static void main(String[] args) { public static void main(String[] args) {
// TLSv1/v1.1 No longer works after upgrade, "No appropriate protocol" error // TLSv1/v1.1 No longer works after upgrade, "No appropriate protocol" error
String property = Security.getProperty("jdk.tls.disabledAlgorithms").replace(", TLSv1", "").replace(", TLSv1.1", ""); String property = Security.getProperty("jdk.tls.disabledAlgorithms").replace(", TLSv1", "").replace(", TLSv1.1", "");
Security.setProperty("jdk.tls.disabledAlgorithms", property); Security.setProperty("jdk.tls.disabledAlgorithms", property);
//blocking 코드 감지 //blocking 코드 감지
BlockHound.builder() // BlockHound.builder()
/** // /**
* mysql r2dbc 에서 호출되는 FileInputStream.readBytes() 가 블로킹코드인데 이를 허용해주도록 한다. // * mysql r2dbc 에서 호출되는 FileInputStream.readBytes() 가 블로킹코드인데 이를 허용해주도록 한다.
* 해당 코드가 어디서 호출되는지 알지 못하는 상태에서 FileInputStream.readBytes() 자체를 허용해주는 것은 좋지 않다. // * 해당 코드가 어디서 호출되는지 알지 못하는 상태에서 FileInputStream.readBytes() 자체를 허용해주는 것은 좋지 않다.
* 누군가 무분별하게 사용하게 되면 검출해 낼 수 없어 시스템의 위험요소로 남게 된다. // * 누군가 무분별하게 사용하게 되면 검출해 낼 수 없어 시스템의 위험요소로 남게 된다.
* r2dbc를 사용하기 위해 FileInputStream.readBytes()를 호출하는 부분만 허용하고 나머지는 여전히 검출대상으로 남기도록 한다. // * r2dbc를 사용하기 위해 FileInputStream.readBytes()를 호출하는 부분만 허용하고 나머지는 여전히 검출대상으로 남기도록 한다.
*/ // */
.allowBlockingCallsInside("dev.miku.r2dbc.mysql.client.ReactorNettyClient", "init") // .allowBlockingCallsInside("dev.miku.r2dbc.mysql.client.ReactorNettyClient", "init")
.install(); // .install();
SpringApplication.run(ReserveItemServiceApplication.class, args); SpringApplication.run(ReserveItemServiceApplication.class, args);
} }
} }

View File

@@ -113,7 +113,6 @@ public class ReserveItemApiController {
@GetMapping("/api/v1/reserve-items/{reserveItemId}") @GetMapping("/api/v1/reserve-items/{reserveItemId}")
@ResponseStatus(HttpStatus.OK) @ResponseStatus(HttpStatus.OK)
public Mono<ReserveItemResponseDto> findById(@PathVariable Long reserveItemId) { public Mono<ReserveItemResponseDto> findById(@PathVariable Long reserveItemId) {
System.out.println("findById : " + reserveItemId);
return reserveItemService.findById(reserveItemId); return reserveItemService.findById(reserveItemId);
} }
@@ -177,7 +176,6 @@ public class ReserveItemApiController {
@PutMapping("/api/v1/reserve-items/{reserveItemId}/inventories") @PutMapping("/api/v1/reserve-items/{reserveItemId}/inventories")
@ResponseStatus(HttpStatus.OK) @ResponseStatus(HttpStatus.OK)
public Mono<Boolean> updateInventory(@PathVariable Long reserveItemId, @RequestBody Integer reserveQty) { public Mono<Boolean> updateInventory(@PathVariable Long reserveItemId, @RequestBody Integer reserveQty) {
System.out.println("update inventories : " + reserveItemId+" : " + reserveQty);
return reserveItemService.updateInventory(reserveItemId, reserveQty); return reserveItemService.updateInventory(reserveItemId, reserveQty);
} }

View File

@@ -1,5 +1,6 @@
package org.egovframe.cloud.reserveitemservice.api.reserveItem.dto; package org.egovframe.cloud.reserveitemservice.api.reserveItem.dto;
import lombok.Builder;
import lombok.Getter; import lombok.Getter;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import lombok.ToString; import lombok.ToString;
@@ -92,6 +93,43 @@ public class ReserveItemSaveRequestDto {
@Size(max = 50) @Size(max = 50)
private String managerContact; //담당자 연락처 private String managerContact; //담당자 연락처
@Builder
public ReserveItemSaveRequestDto(String reserveItemName, Long locationId, String categoryId, Integer totalQty,
Integer inventoryQty, LocalDateTime operationStartDate, LocalDateTime operationEndDate,
String reserveMethodId, String reserveMeansId, LocalDateTime requestStartDate,
LocalDateTime requestEndDate, Boolean isPeriod, Integer periodMaxCount, String externalUrl,
String selectionMeansId, Boolean isPaid, BigDecimal usageCost, Boolean isUse, String purpose,
String address, String targetId, String excluded, String homepage, String contact, String managerDept,
String managerName, String managerContact) {
this.reserveItemName = reserveItemName;
this.locationId = locationId;
this.categoryId = categoryId;
this.totalQty = totalQty;
this.inventoryQty = inventoryQty;
this.operationStartDate = operationStartDate;
this.operationEndDate = operationEndDate;
this.reserveMethodId = reserveMethodId;
this.reserveMeansId = reserveMeansId;
this.requestStartDate = requestStartDate;
this.requestEndDate = requestEndDate;
this.isPeriod = isPeriod;
this.periodMaxCount = periodMaxCount;
this.externalUrl = externalUrl;
this.selectionMeansId = selectionMeansId;
this.isPaid = isPaid;
this.usageCost = usageCost;
this.isUse = isUse;
this.purpose = purpose;
this.address = address;
this.targetId = targetId;
this.excluded = excluded;
this.homepage = homepage;
this.contact = contact;
this.managerDept = managerDept;
this.managerName = managerName;
this.managerContact = managerContact;
}
public ReserveItem toEntity() { public ReserveItem toEntity() {
return ReserveItem.builder() return ReserveItem.builder()
.reserveItemName(this.reserveItemName) .reserveItemName(this.reserveItemName)

View File

@@ -1,5 +1,6 @@
package org.egovframe.cloud.reserveitemservice.api.reserveItem.dto; package org.egovframe.cloud.reserveitemservice.api.reserveItem.dto;
import lombok.Builder;
import lombok.Getter; import lombok.Getter;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import lombok.ToString; import lombok.ToString;
@@ -61,7 +62,6 @@ public class ReserveItemUpdateRequestDto {
private String externalUrl; //외부링크 private String externalUrl; //외부링크
@NotBlank @NotBlank
private String selectionMeansId; //선별 방법 - 공통코드 reserve-selection private String selectionMeansId; //선별 방법 - 공통코드 reserve-selection
@NotNull
private Boolean isPaid; // 유/무료 - false: 무료, true: 유료 private Boolean isPaid; // 유/무료 - false: 무료, true: 유료
private BigDecimal usageCost; //이용 요금 private BigDecimal usageCost; //이용 요금
private Boolean isUse; //사용여부 private Boolean isUse; //사용여부
@@ -83,6 +83,43 @@ public class ReserveItemUpdateRequestDto {
@Size(max = 50) @Size(max = 50)
private String managerContact; //담당자 연락처 private String managerContact; //담당자 연락처
@Builder
public ReserveItemUpdateRequestDto(String reserveItemName, Long locationId, String categoryId,
Integer totalQty, Integer inventoryQty, LocalDateTime operationStartDate, LocalDateTime operationEndDate,
String reserveMethodId, String reserveMeansId, LocalDateTime requestStartDate,
LocalDateTime requestEndDate, Boolean isPeriod, Integer periodMaxCount, String externalUrl,
String selectionMeansId, Boolean isPaid, BigDecimal usageCost, Boolean isUse, String purpose,
String address, String targetId, String excluded, String homepage, String contact, String managerDept,
String managerName, String managerContact) {
this.reserveItemName = reserveItemName;
this.locationId = locationId;
this.categoryId = categoryId;
this.totalQty = totalQty;
this.inventoryQty = inventoryQty;
this.operationStartDate = operationStartDate;
this.operationEndDate = operationEndDate;
this.reserveMethodId = reserveMethodId;
this.reserveMeansId = reserveMeansId;
this.requestStartDate = requestStartDate;
this.requestEndDate = requestEndDate;
this.isPeriod = isPeriod;
this.periodMaxCount = periodMaxCount;
this.externalUrl = externalUrl;
this.selectionMeansId = selectionMeansId;
this.isPaid = isPaid;
this.usageCost = usageCost;
this.isUse = isUse;
this.purpose = purpose;
this.address = address;
this.targetId = targetId;
this.excluded = excluded;
this.homepage = homepage;
this.contact = contact;
this.managerDept = managerDept;
this.managerName = managerName;
this.managerContact = managerContact;
}
public ReserveItem toEntity() { public ReserveItem toEntity() {
return ReserveItem.builder() return ReserveItem.builder()
.reserveItemName(this.reserveItemName) .reserveItemName(this.reserveItemName)

View File

@@ -278,7 +278,6 @@ public class ReserveItem extends BaseEntity {
* @return * @return
*/ */
public ReserveItem update(ReserveItemUpdateRequestDto updateRequestDto) { public ReserveItem update(ReserveItemUpdateRequestDto updateRequestDto) {
System.out.println("============ ?? : " + updateRequestDto.toString());
this.reserveItemName = updateRequestDto.getReserveItemName(); this.reserveItemName = updateRequestDto.getReserveItemName();
this.locationId = updateRequestDto.getLocationId(); this.locationId = updateRequestDto.getLocationId();
this.categoryId = updateRequestDto.getCategoryId(); this.categoryId = updateRequestDto.getCategoryId();

View File

@@ -235,7 +235,6 @@ public class ReserveItemRepositoryImpl implements ReserveItemRepositoryCustom{
whereCriteria.add(where("use_at").isTrue()); whereCriteria.add(where("use_at").isTrue());
whereCriteria.add(where("reserve_method_id").is("internet")); whereCriteria.add(where("reserve_method_id").is("internet"));
} }
System.out.println(whereCriteria.toString());
return whereCriteria; return whereCriteria;
} }

View File

@@ -1,144 +1,183 @@
package org.egovframe.cloud.reserveitemservice.api.location; package org.egovframe.cloud.reserveitemservice.api.location;
import static org.junit.jupiter.api.Assertions.*;
import org.egovframe.cloud.reserveitemservice.api.location.dto.LocationSaveRequestDto; import org.egovframe.cloud.reserveitemservice.api.location.dto.LocationSaveRequestDto;
import org.egovframe.cloud.reserveitemservice.api.location.dto.LocationUpdateRequestDto; import org.egovframe.cloud.reserveitemservice.api.location.dto.LocationUpdateRequestDto;
import org.egovframe.cloud.reserveitemservice.config.R2dbcConfig; import org.egovframe.cloud.reserveitemservice.config.R2dbcConfig;
import org.egovframe.cloud.reserveitemservice.domain.location.Location; import org.egovframe.cloud.reserveitemservice.domain.location.Location;
import org.egovframe.cloud.reserveitemservice.domain.location.LocationRepository; import org.egovframe.cloud.reserveitemservice.domain.location.LocationRepository;
import org.junit.jupiter.api.BeforeEach; import org.egovframe.cloud.reserveitemservice.domain.reserveItem.ReserveItem;
import org.egovframe.cloud.reserveitemservice.domain.reserveItem.ReserveItemRepository;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.mockito.ArgumentMatchers;
import org.mockito.BDDMockito;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.context.annotation.Import; import org.springframework.context.annotation.Import;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.data.domain.Pageable;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
import org.springframework.test.context.ActiveProfiles; import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.TestPropertySource; import org.springframework.test.context.TestPropertySource;
import org.springframework.test.web.reactive.server.WebTestClient; import org.springframework.test.web.reactive.server.WebTestClient;
import org.springframework.web.reactive.function.BodyInserters; import org.springframework.web.reactive.function.BodyInserters;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@EnableConfigurationProperties @EnableConfigurationProperties
@TestPropertySource(properties = {"spring.config.location=classpath:application-test.yml"}) @TestPropertySource(properties = {"spring.config.location=classpath:application-test.yml"})
@ActiveProfiles("test") @ActiveProfiles("test")
@Import({R2dbcConfig.class}) @Import({R2dbcConfig.class})
class LocationApiControllerTest { public class LocationApiControllerTest {
@MockBean @Autowired
private LocationRepository locationRepository; private LocationRepository locationRepository;
@Autowired @Autowired
private WebTestClient webTestClient; private ReserveItemRepository reserveItemRepository;
private final static String API_URL = "/api/v1/locations"; @Autowired
WebTestClient webTestClient;
private Location location = Location.builder() private static final String API_URL = "/api/v1/locations";
.locationId(1L)
.locationName("location")
.isUse(true)
.sortSeq(1)
.build();
@BeforeEach @AfterEach
public void setup() { public void tearDown() {
BDDMockito.when(locationRepository.findById(ArgumentMatchers.anyLong())) reserveItemRepository.deleteAll().block();
.thenReturn(Mono.just(location)); locationRepository.deleteAll().block();
//조회조건 있는 경우 }
BDDMockito.when(locationRepository.findAllByLocationNameContainingOrderBySortSeq(
ArgumentMatchers.anyString(), ArgumentMatchers.any(Pageable.class)))
.thenReturn(Flux.just(location));
BDDMockito.when(locationRepository.countAllByLocationNameContaining(ArgumentMatchers.anyString()))
.thenReturn(Mono.just(1L));
//조회조건 없는 경우
BDDMockito.when(locationRepository.findAllByOrderBySortSeq(ArgumentMatchers.any(Pageable.class)))
.thenReturn(Flux.just(location));
BDDMockito.when(locationRepository.count()).thenReturn(Mono.just(1L));
BDDMockito.when(locationRepository.save(ArgumentMatchers.any(Location.class))) @Test
.thenReturn(Mono.just(location)); public void 한건조회_성공() throws Exception {
} Location location1 = locationRepository.save(Location.builder()
.locationName("location1")
.isUse(true)
.sortSeq(1)
.build()).block();
assertNotNull(location1);
@Test webTestClient.get()
public void 한건조회_성공() throws Exception { .uri(API_URL+"/{locationId}", location1.getLocationId())
webTestClient.get() .exchange()
.uri(API_URL+"/{locationId}", location.getLocationId()) .expectStatus().isOk()
.exchange() .expectBody()
.expectStatus().isOk() .jsonPath("$.locationName").isEqualTo(location1.getLocationName());
.expectBody() }
.jsonPath("$.locationName").isEqualTo(location.getLocationName());
}
@Test
public void 조회조건있는경우_페이지목록조회_성공() throws Exception {
webTestClient.get()
.uri(API_URL+"?keywordType=locationName&keyword=location&page=0&size=3")
.exchange()
.expectStatus().isOk()
.expectBody()
.jsonPath("$.totalElements").isEqualTo(1)
.jsonPath("$.content[0].locationName").isEqualTo(location.getLocationName());
}
@Test
public void 조회조건없는경우_페이지목록조회_성공() throws Exception {
webTestClient.get()
.uri(API_URL+"?page=0&size=3")
.exchange()
.expectStatus().isOk()
.expectBody()
.jsonPath("$.totalElements").isEqualTo(1)
.jsonPath("$.content[0].locationName").isEqualTo(location.getLocationName());
}
@Test
public void 한건저장_성공() throws Exception {
webTestClient.post()
.uri(API_URL)
.contentType(MediaType.APPLICATION_JSON)
.body(BodyInserters.fromValue(LocationSaveRequestDto.builder()
.locationName(location.getLocationName())
.isUse(location.getIsUse())
.sortSeq(location.getSortSeq())
.build()))
.exchange()
.expectStatus().isCreated()
.expectBody().jsonPath("$.locationName").isEqualTo(location.getLocationName());
}
@Test
public void 한건수정_성공() throws Exception {
webTestClient.put()
.uri(API_URL+"/{locationId}", location.getLocationId())
.contentType(MediaType.APPLICATION_JSON)
.body(BodyInserters.fromValue(LocationUpdateRequestDto.builder()
.locationName("updateLocation")
.isUse(location.getIsUse())
.sortSeq(location.getSortSeq())
.build()))
.exchange()
.expectStatus().isNoContent();
}
@Test
public void 한건삭제_참조데이터존재_삭제실패() throws Exception {
BDDMockito.when(locationRepository.delete(ArgumentMatchers.any(Location.class)))
.thenReturn(Mono.error(new DataIntegrityViolationException("integrity test")));
webTestClient.delete()
.uri(API_URL+"/{locationId}", 1L)
.exchange()
.expectStatus().isBadRequest();
}
} @Test
public void 조회조건있는경우_페이지목록조회_성공() throws Exception {
Location location1 = locationRepository.save(Location.builder()
.locationName("location1")
.isUse(true)
.sortSeq(1)
.build()).block();
assertNotNull(location1);
webTestClient.get()
.uri(API_URL+"?keywordType=locationName&keyword=location&page=0&size=3")
.exchange()
.expectStatus().isOk()
.expectBody()
.jsonPath("$.totalElements").isEqualTo(1)
.jsonPath("$.content[0].locationName").isEqualTo(location1.getLocationName());
}
@Test
public void 조회조건없는경우_페이지목록조회_성공() throws Exception {
Location location1 = locationRepository.save(Location.builder()
.locationName("location1")
.isUse(true)
.sortSeq(1)
.build()).block();
assertNotNull(location1);
webTestClient.get()
.uri(API_URL+"?page=0&size=3")
.exchange()
.expectStatus().isOk()
.expectBody()
.jsonPath("$.totalElements").isEqualTo(1)
.jsonPath("$.content[0].locationName").isEqualTo(location1.getLocationName());
}
@Test
public void 한건저장_성공() throws Exception {
webTestClient.post()
.uri(API_URL)
.contentType(MediaType.APPLICATION_JSON)
.body(BodyInserters.fromValue(LocationSaveRequestDto.builder()
.locationName("location1")
.isUse(true)
.sortSeq(1)
.build()))
.exchange()
.expectStatus().isCreated()
.expectBody().jsonPath("$.locationName").isEqualTo("location1");
}
@Test
public void 한건수정_성공() throws Exception {
Location location1 = locationRepository.save(Location.builder()
.locationName("location1")
.isUse(true)
.sortSeq(1)
.build()).block();
assertNotNull(location1);
webTestClient.put()
.uri(API_URL+"/{locationId}", location1.getLocationId())
.contentType(MediaType.APPLICATION_JSON)
.body(BodyInserters.fromValue(LocationUpdateRequestDto.builder()
.locationName("updateLocation")
.isUse(location1.getIsUse())
.sortSeq(location1.getSortSeq())
.build()))
.exchange()
.expectStatus().isNoContent();
Location updatedLocation = locationRepository.findById(location1.getLocationId()).block();
assertNotNull(updatedLocation);
assertEquals(updatedLocation.getLocationName(), "updateLocation");
}
@Test
public void 한건삭제_참조데이터존재_삭제실패() throws Exception {
Location location1 = locationRepository.save(Location.builder()
.locationName("location1")
.isUse(true)
.sortSeq(1)
.build()).block();
assertNotNull(location1);
reserveItemRepository.save(ReserveItem.builder()
.locationId(location1.getLocationId())
.categoryId("test")
.build()).block();
webTestClient.delete()
.uri(API_URL+"/{locationId}", location1.getLocationId())
.exchange()
.expectStatus().isBadRequest();
}
@Test
public void 한건삭제_성공() throws Exception {
Location location1 = locationRepository.save(Location.builder()
.locationName("location1")
.isUse(true)
.sortSeq(1)
.build()).block();
assertNotNull(location1);
webTestClient.delete()
.uri(API_URL+"/{locationId}", location1.getLocationId())
.exchange()
.expectStatus().isNoContent();
}
}

View File

@@ -1,14 +1,30 @@
package org.egovframe.cloud.reserveitemservice.api.reserveItem; package org.egovframe.cloud.reserveitemservice.api.reserveItem;
import static org.assertj.core.api.Assertions.*;
import static org.junit.jupiter.api.Assertions.*;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.egovframe.cloud.common.exception.dto.ErrorCode;
import org.egovframe.cloud.common.exception.dto.ErrorResponse;
import org.egovframe.cloud.reserveitemservice.api.reserveItem.dto.ReserveItemMainResponseDto;
import org.egovframe.cloud.reserveitemservice.api.reserveItem.dto.ReserveItemRequestDto; import org.egovframe.cloud.reserveitemservice.api.reserveItem.dto.ReserveItemRequestDto;
import org.egovframe.cloud.reserveitemservice.api.reserveItem.dto.ReserveItemResponseDto;
import org.egovframe.cloud.reserveitemservice.api.reserveItem.dto.ReserveItemSaveRequestDto;
import org.egovframe.cloud.reserveitemservice.api.reserveItem.dto.ReserveItemUpdateRequestDto;
import org.egovframe.cloud.reserveitemservice.config.R2dbcConfig; import org.egovframe.cloud.reserveitemservice.config.R2dbcConfig;
import org.egovframe.cloud.reserveitemservice.domain.code.Code; import org.egovframe.cloud.reserveitemservice.domain.code.Code;
import org.egovframe.cloud.reserveitemservice.domain.location.Location; import org.egovframe.cloud.reserveitemservice.domain.location.Location;
import org.egovframe.cloud.reserveitemservice.domain.location.LocationRepository;
import org.egovframe.cloud.reserveitemservice.domain.reserveItem.ReserveItem; import org.egovframe.cloud.reserveitemservice.domain.reserveItem.ReserveItem;
import org.egovframe.cloud.reserveitemservice.domain.reserveItem.ReserveItemRepository; import org.egovframe.cloud.reserveitemservice.domain.reserveItem.ReserveItemRepository;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.mockito.ArgumentMatchers; import org.mockito.ArgumentMatchers;
import org.mockito.BDDMockito; import org.mockito.BDDMockito;
@@ -17,7 +33,10 @@ import org.springframework.boot.context.properties.EnableConfigurationProperties
import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.context.annotation.Import; import org.springframework.context.annotation.Import;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Pageable;
import org.springframework.data.r2dbc.core.R2dbcEntityTemplate;
import org.springframework.http.HttpMethod;
import org.springframework.test.context.ActiveProfiles; import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.TestPropertySource; import org.springframework.test.context.TestPropertySource;
import org.springframework.test.web.reactive.server.WebTestClient; import org.springframework.test.web.reactive.server.WebTestClient;
@@ -29,136 +48,243 @@ import reactor.core.publisher.Mono;
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@EnableConfigurationProperties @EnableConfigurationProperties
@TestPropertySource(properties = {"spring.config.location=classpath:application-test.yml"}) @TestPropertySource(properties = {"spring.config.location=classpath:application-test.yml"})
@ActiveProfiles(profiles = "test") @ActiveProfiles("test")
@Import({R2dbcConfig.class}) @Import({R2dbcConfig.class})
class ReserveItemApiControllerTest { class ReserveItemApiControllerTest {
@Autowired
private LocationRepository locationRepository;
@MockBean @Autowired
ReserveItemRepository reserveItemRepository; private ReserveItemRepository reserveItemRepository;
@Autowired
private R2dbcEntityTemplate entityTemplate;
@Autowired @Autowired
WebTestClient webTestClient; WebTestClient webTestClient;
private final static String API_URL = "/api/v1/reserve-items"; private final static String API_URL = "/api/v1/reserve-items";
Code category = null;
Location location = null;
ReserveItem reserveItem = ReserveItem.builder().build();
@AfterEach
public void tearDown() {
entityTemplate.delete(Code.class).all().block();
reserveItemRepository.deleteAll().block();
locationRepository.deleteAll().block();
}
@BeforeEach
public void setUp() {
category = Code.builder().codeName("category").codeId("category").parentCodeId("reserve-category").build();
entityTemplate.insert(Code.class)
.using(category).block();
location = locationRepository.save(Location.builder()
.locationName("location1")
.isUse(true)
.sortSeq(1)
.build()).block();
assertNotNull(location);
reserveItem = ReserveItem.builder()
.categoryId(category.getCodeId())
.locationId(location.getLocationId())
.reserveItemName("test")
.isUse(Boolean.TRUE)
.operationStartDate(LocalDateTime.of(2021, 10, 1, 1, 1))
.operationEndDate(LocalDateTime.of(2021, 10, 31, 23, 59))
.reserveMethodId("internet")
.reserveMeansId("realtime")
.requestStartDate(LocalDateTime.of(2021, 10, 1, 1, 1))
.requestEndDate(LocalDateTime.of(2021, 10, 31, 23, 59))
.totalQty(100)
.inventoryQty(100)
.isPeriod(Boolean.FALSE)
.selectionMeansId("evaluate")
.build();
}
@Test @Test
public void 사용자별_검색_목록_조회_성공() throws Exception { public void 사용자목록조회_성공() throws Exception {
LocalDateTime startDate = LocalDateTime.of(2021, 1, 28, 1,1);
LocalDateTime endDate = LocalDateTime.of(2021, 12, 6, 1,1);
Location location = Location.builder() ReserveItem saved = reserveItemRepository.save(reserveItem).block();
.locationId(1L) assertNotNull(saved);
.locationName("location")
.sortSeq(1)
.isUse(true)
.build();
ReserveItem reserveItem = ReserveItem.builder()
.reserveItemId(1L)
.location(location)
.locationId(location.getLocationId())
.reserveItemName("test")
.categoryId("education")
.categoryName("교육")
.totalQty(100)
.inventoryQty(80)
.operationEndDate(endDate)
.operationStartDate(startDate)
.isPeriod(false)
.isUse(true)
.build();
BDDMockito.when(reserveItemRepository.searchForUser(ArgumentMatchers.anyString(), webTestClient.method(HttpMethod.GET)
ArgumentMatchers.any(ReserveItemRequestDto.class), ArgumentMatchers.any(Pageable.class))) .uri("/api/v1/"+category.getCodeId()+"/reserve-items"+"?page=0&size=3&isUse=true")
.thenReturn(Flux.just(reserveItem)); .exchange()
.expectStatus().isOk()
.expectBody()
.jsonPath("$.totalElements").isEqualTo(1)
.jsonPath("$.content[0].reserveItemName").isEqualTo(reserveItem.getReserveItemName());
}
BDDMockito.when(reserveItemRepository.searchCountForUser(ArgumentMatchers.anyString(), @Test
ArgumentMatchers.any(ReserveItemRequestDto.class), ArgumentMatchers.any(Pageable.class))) public void 관리자목록조회_성공() throws Exception {
.thenReturn(Mono.just(1L));
webTestClient.get() ReserveItem saved = reserveItemRepository.save(reserveItem).block();
.uri("/api/v1/{categoryId}/reserve-items?keywordType=locationName&keyword=location&page=0&size=3", "education") assertNotNull(saved);
.exchange()
.expectStatus().isOk(); webTestClient.method(HttpMethod.GET)
.uri(API_URL+"?page=0&size=3&isUse=false")
.exchange()
.expectStatus().isOk()
.expectBody()
.jsonPath("$.totalElements").isEqualTo(1)
.jsonPath("$.content[0].reserveItemName").isEqualTo(reserveItem.getReserveItemName());
}
@Test
public void 한건조회_성공() throws Exception {
ReserveItem saved = reserveItemRepository.save(reserveItem).block();
assertNotNull(saved);
ReserveItemResponseDto responseBody = webTestClient.get()
.uri(API_URL+"/{reserveItemId}", saved.getReserveItemId())
.exchange()
.expectStatus().isOk()
.expectBody(ReserveItemResponseDto.class)
.returnResult().getResponseBody();
assertThat(responseBody.getCategoryId()).isEqualTo(category.getCodeId());
assertThat(responseBody.getReserveItemName()).isEqualTo(saved.getReserveItemName());
} }
@Test @Test
public void main_예약물품조회_성공() throws Exception { public void 사용자_포털_메인_예약목록_조회_성공() throws Exception {
BDDMockito.when(reserveItemRepository.findCodeDetail(ArgumentMatchers.anyString())) ReserveItem saved = reserveItemRepository.save(reserveItem).block();
.thenReturn(Flux.fromIterable(Arrays.asList(Code.builder().codeId("education").codeName("교육").build(), assertNotNull(saved);
Code.builder().codeId("equipment").codeName("장비").build(),
Code.builder().codeId("space").codeName("장소").build())));
LocalDateTime startDate = LocalDateTime.of(2021, 1, 28, 1,1); Map<String, Collection<ReserveItemMainResponseDto>> responseBody = webTestClient.get()
LocalDateTime endDate = LocalDateTime.of(2021, 12, 6, 1,1); .uri(API_URL+"/latest/3")
Location location = Location.builder()
.locationId(1L)
.locationName("location")
.sortSeq(1)
.isUse(true)
.build();
ReserveItem reserveItem1 = ReserveItem.builder()
.reserveItemId(1L)
.location(location)
.locationId(location.getLocationId())
.reserveItemName("test")
.categoryId("education")
.categoryName("교육")
.totalQty(100)
.inventoryQty(80)
.operationEndDate(endDate)
.operationStartDate(startDate)
.reserveMethodId("visit")
.isPeriod(false)
.isUse(true)
.build();
ReserveItem reserveItem2 = ReserveItem.builder()
.reserveItemId(1L)
.location(location)
.locationId(location.getLocationId())
.reserveItemName("test")
.categoryId("education")
.categoryName("장비")
.totalQty(100)
.inventoryQty(80)
.operationEndDate(endDate)
.operationStartDate(startDate)
.reserveMethodId("visit")
.isPeriod(false)
.isUse(true)
.build();
ReserveItem reserveItem3 = ReserveItem.builder()
.reserveItemId(1L)
.location(location)
.locationId(location.getLocationId())
.reserveItemName("test")
.categoryId("education")
.categoryName("공간")
.totalQty(100)
.inventoryQty(80)
.operationEndDate(endDate)
.operationStartDate(startDate)
.reserveMethodId("visit")
.isPeriod(false)
.isUse(true)
.build();
reserveItem1.setCreateDate(LocalDateTime.now());
reserveItem2.setCreateDate(LocalDateTime.now());
reserveItem3.setCreateDate(LocalDateTime.now());
BDDMockito.when(reserveItemRepository.findLatestByCategory(ArgumentMatchers.anyInt(), ArgumentMatchers.anyString()))
.thenReturn(Flux.fromIterable(Arrays.asList(reserveItem1, reserveItem2, reserveItem3)));
webTestClient.get()
.uri("/api/v1/reserve-items/latest/3")
.exchange() .exchange()
.expectStatus().isOk(); .expectStatus().isOk()
.expectBody(new ParameterizedTypeReference<Map<String, Collection<ReserveItemMainResponseDto>>>() {
})
.returnResult().getResponseBody();
assertThat(responseBody.keySet().size()).isEqualTo(1);
assertThat(responseBody.keySet().contains(category.getCodeId())).isTrue();
Collection<ReserveItemMainResponseDto> reserveItemMainResponseDtos = responseBody.get(category.getCodeId());
reserveItemMainResponseDtos.stream().forEach(reserveItemMainResponseDto -> {
assertThat(reserveItemMainResponseDto.getReserveItemName().equals(saved.getReserveItemName()));
});
}
@Test
public void 한건_등록_성공() throws Exception {
ReserveItemSaveRequestDto requestDto = ReserveItemSaveRequestDto.builder()
.reserveItemName(reserveItem.getReserveItemName())
.categoryId(reserveItem.getCategoryId())
.locationId(reserveItem.getLocationId())
.inventoryQty(reserveItem.getInventoryQty())
.totalQty(reserveItem.getTotalQty())
.operationStartDate(reserveItem.getOperationStartDate())
.operationEndDate(reserveItem.getOperationEndDate())
.reserveMethodId(reserveItem.getReserveMethodId())
.reserveMeansId(reserveItem.getReserveMeansId())
.isUse(reserveItem.getIsUse())
.requestStartDate(reserveItem.getRequestStartDate())
.requestEndDate(reserveItem.getRequestEndDate())
.isPeriod(reserveItem.getIsPeriod())
.selectionMeansId(reserveItem.getSelectionMeansId())
.build();
ReserveItemResponseDto responseBody = webTestClient.post()
.uri(API_URL)
.bodyValue(requestDto)
.exchange()
.expectStatus().isCreated()
.expectBody(ReserveItemResponseDto.class)
.returnResult().getResponseBody();
System.out.println(responseBody);
assertThat(responseBody.getReserveItemName()).isEqualTo(requestDto.getReserveItemName());
}
@Test
public void 한건_수정_성공() throws Exception {
ReserveItem saved = reserveItemRepository.save(reserveItem).block();
assertNotNull(saved);
ReserveItemUpdateRequestDto requestDto = ReserveItemUpdateRequestDto.builder()
.reserveItemName("update")
.categoryId(reserveItem.getCategoryId())
.locationId(reserveItem.getLocationId())
.inventoryQty(reserveItem.getInventoryQty())
.totalQty(reserveItem.getTotalQty())
.operationStartDate(reserveItem.getOperationStartDate())
.operationEndDate(reserveItem.getOperationEndDate())
.reserveMethodId(reserveItem.getReserveMethodId())
.reserveMeansId(reserveItem.getReserveMeansId())
.isUse(reserveItem.getIsUse())
.requestStartDate(reserveItem.getRequestStartDate())
.requestEndDate(reserveItem.getRequestEndDate())
.isPeriod(reserveItem.getIsPeriod())
.selectionMeansId(reserveItem.getSelectionMeansId())
.build();
webTestClient.put()
.uri(API_URL+"/"+saved.getReserveItemId())
.bodyValue(requestDto)
.exchange()
.expectStatus().isNoContent();
ReserveItem findbyid = reserveItemRepository.findById(saved.getReserveItemId()).block();
assertThat(findbyid.getReserveItemName()).isEqualTo("update");
}
@Test
public void 사용여부_false_수정_성공() throws Exception {
ReserveItem saved = reserveItemRepository.save(reserveItem).block();
assertNotNull(saved);
webTestClient.put()
.uri(API_URL+"/"+saved.getReserveItemId()+"/false")
.exchange()
.expectStatus().isNoContent();
ReserveItem findbyid = reserveItemRepository.findById(saved.getReserveItemId()).block();
assertThat(findbyid.getIsUse()).isEqualTo(Boolean.FALSE);
}
@Test
public void 한건_저장_validation_실패() throws Exception {
ReserveItemSaveRequestDto requestDto = ReserveItemSaveRequestDto.builder()
.reserveItemName(reserveItem.getReserveItemName())
.categoryId(reserveItem.getCategoryId())
.locationId(reserveItem.getLocationId())
.inventoryQty(reserveItem.getInventoryQty())
.totalQty(reserveItem.getTotalQty())
.operationStartDate(reserveItem.getOperationStartDate())
.operationEndDate(reserveItem.getOperationEndDate())
.reserveMethodId(reserveItem.getReserveMethodId())
.reserveMeansId(reserveItem.getReserveMeansId())
.isUse(reserveItem.getIsUse())
.isPeriod(reserveItem.getIsPeriod())
.selectionMeansId(reserveItem.getSelectionMeansId())
.build();
ErrorResponse responseBody = webTestClient.post()
.uri(API_URL)
.bodyValue(requestDto)
.exchange()
.expectStatus().isBadRequest()
.expectBody(ErrorResponse.class)
.returnResult().getResponseBody();
assertThat(responseBody.getCode()).isEqualTo(ErrorCode.INVALID_INPUT_VALUE.getCode());
assertThat(responseBody.getErrors().size()).isEqualTo(1);
responseBody.getErrors().stream().forEach(fieldError -> {
assertThat(fieldError.getField()).isEqualTo("requestStartDate");
System.out.println(fieldError.getMessage());
});
} }
} }

View File

@@ -21,7 +21,7 @@ public class R2dbcConfig{
@Bean @Bean
public H2ConnectionFactory connectionFactory() { public H2ConnectionFactory connectionFactory() {
return new H2ConnectionFactory(H2ConnectionConfiguration.builder() return new H2ConnectionFactory(H2ConnectionConfiguration.builder()
.tcp("localhost", "~/querydsl") .inMemory("testdb")
.property(H2ConnectionOption.DB_CLOSE_DELAY, "-1") .property(H2ConnectionOption.DB_CLOSE_DELAY, "-1")
.username("sa") .username("sa")
.build()); .build());

View File

@@ -2,20 +2,6 @@ spring:
application: application:
name: reserve-item-service name: reserve-item-service
datasource:
url: jdbc:h2:mem:testdb;MODE=MYSQL;DB_CLOSE_DELAY=-1;DATABASE_TO_UPPER=false
username: sa
password:
driver-class-name: org.h2.Driver
jpa:
hibernate:
generate-ddl: true
ddl-auto: create-drop
properties:
hibernate:
format_sql: true
default_batch_fetch_size: 1000
show-sql: true
h2: h2:
console: console:
enabled: true enabled: true

View File

@@ -1,14 +1,25 @@
CREATE TABLE IF NOT EXISTS location( CREATE TABLE IF NOT EXISTS `code` (
location_id BIGINT AUTO_INCREMENT, `code_id` varchar(20) NOT NULL COMMENT '코드 id',
location_name VARCHAR(200), `code_name` varchar(500) NOT NULL COMMENT '코드 명',
use_at tinyint(1) default 1 null, `parent_code_id` varchar(20) DEFAULT NULL COMMENT '부모 코드 id',
sort_seq smallint(3) null, use_at BOOLEAN NULL DEFAULT TRUE COMMENT '사용 여부',
create_date DATE null, PRIMARY KEY (`code_id`)
modified_date DATE null, ) ;
created_by VARCHAR(255) null,
last_modified_by VARCHAR(255) null, -- location Table Create SQL
CONSTRAINT PERSON_PK PRIMARY KEY (location_id) CREATE TABLE IF NOT EXISTS location
); (
location_id BIGINT NOT NULL AUTO_INCREMENT COMMENT '지역 id',
location_name VARCHAR(200) NULL COMMENT '지역 이름',
sort_seq SMALLINT(3) NULL COMMENT '정렬 순서',
use_at BOOLEAN NULL DEFAULT TRUE COMMENT '사용 여부',
created_by VARCHAR(255) NULL COMMENT '생성자',
create_date DATETIME NULL COMMENT '생성일',
last_modified_by VARCHAR(255) NULL COMMENT '수정자',
modified_date DATETIME NULL COMMENT '수정일',
PRIMARY KEY (location_id)
) ;
-- reserve_item Table Create SQL -- reserve_item Table Create SQL
@@ -18,20 +29,21 @@ CREATE TABLE IF NOT EXISTS reserve_item
reserve_item_name VARCHAR(200) NULL COMMENT '예약 물품 이름', reserve_item_name VARCHAR(200) NULL COMMENT '예약 물품 이름',
location_id BIGINT NULL COMMENT '지역 id', location_id BIGINT NULL COMMENT '지역 id',
category_id VARCHAR(20) NULL COMMENT '예약유형 - 공통코드 reserve-category', category_id VARCHAR(20) NULL COMMENT '예약유형 - 공통코드 reserve-category',
capacity_count MEDIUMINT(5) NULL COMMENT '재고/수용인원 수', total_qty BIGINT(18) NULL COMMENT '재고/수용인원 수',
inventory_qty BIGINT(18) NULL COMMENT '현재 남은 재고/수용인원 수',
operation_start_date DATETIME NULL COMMENT '운영 시작 일', operation_start_date DATETIME NULL COMMENT '운영 시작 일',
operation_end_date DATETIME NULL COMMENT '운영 종료 일', operation_end_date DATETIME NULL COMMENT '운영 종료 일',
reserve_method_id VARCHAR(20) NULL COMMENT '예약 방법 - 공통코드 reserve-method', reserve_method_id VARCHAR(20) NULL COMMENT '예약 방법 - 공통코드 reserve-method',
reserve_means_id VARCHAR(20) NULL COMMENT '예약 구분 (인터넷 예약 시) - 공통코드 reserve-means', reserve_means_id VARCHAR(20) NULL COMMENT '예약 구분 (인터넷 예약 시) - 공통코드 reserve-means',
request_start_date DATETIME NULL COMMENT '예약 신청 시작 일시', request_start_date DATETIME NULL COMMENT '예약 신청 시작 일시',
request_end_date DATETIME NULL COMMENT '예약 신청 종료 일시', request_end_date DATETIME NULL COMMENT '예약 신청 종료 일시',
period_at TINYINT(1) NULL DEFAULT 0 COMMENT '기간 지정 가능 여부 - true: 지정 가능, false: 지정 불가', period_at BOOLEAN NULL DEFAULT FALSE COMMENT '기간 지정 가능 여부 - true: 지정 가능, false: 지정 불가',
period_max_count SMALLINT(3) NULL COMMENT '최대 예약 가능 일 수', period_max_count SMALLINT(3) NULL COMMENT '최대 예약 가능 일 수',
external_url VARCHAR(500) NULL COMMENT '외부링크', external_url VARCHAR(500) NULL COMMENT '외부링크',
selection_means_id VARCHAR(20) NULL COMMENT '선별 방법 - 공통코드 reserve-selection-means', selection_means_id VARCHAR(20) NULL COMMENT '선별 방법 - 공통코드 reserve-selection-means',
free_at TINYINT(1) NULL DEFAULT 1 COMMENT '유/무료 - true: 무료, false: 유료', paid_at BOOLEAN NULL DEFAULT FALSE COMMENT '유/무료 - false: 무료, true: 유료',
usage_cost DECIMAL(18, 0) NULL COMMENT '이용 요금', usage_cost DECIMAL(18, 0) NULL COMMENT '이용 요금',
use_at TINYINT(1) NULL DEFAULT 1 COMMENT '사용 여부', use_at BOOLEAN NULL DEFAULT TRUE COMMENT '사용 여부',
purpose_content VARCHAR(4000) NULL COMMENT '용도', purpose_content VARCHAR(4000) NULL COMMENT '용도',
item_addr VARCHAR(500) NULL COMMENT '주소', item_addr VARCHAR(500) NULL COMMENT '주소',
target_id VARCHAR(20) NULL COMMENT '이용 대상 - 공통코드 reserve-target', target_id VARCHAR(20) NULL COMMENT '이용 대상 - 공통코드 reserve-target',
@@ -45,5 +57,10 @@ CREATE TABLE IF NOT EXISTS reserve_item
created_by VARCHAR(255) NULL COMMENT '생성자', created_by VARCHAR(255) NULL COMMENT '생성자',
modified_date DATETIME NULL COMMENT '수정일', modified_date DATETIME NULL COMMENT '수정일',
last_modified_by VARCHAR(255) NULL COMMENT '수정자', last_modified_by VARCHAR(255) NULL COMMENT '수정자',
PRIMARY KEY (reserve_item_id) PRIMARY KEY (reserve_item_id),
); CONSTRAINT FK_reserve_item_location_id FOREIGN KEY (location_id)
REFERENCES location (location_id) ON DELETE RESTRICT ON UPDATE RESTRICT
) ;

View File

@@ -1,8 +1,6 @@
# openjdk8 base image # openjdk8 base image
FROM openjdk:8-jre-alpine FROM openjdk:8-jre-alpine
# config server uri: dockder run --e 로 변경 가능
ENV SPRING_CLOUD_CONFIG_URI https://egov-config.paas-ta.org
# jar 파일이 복사되는 위치 # jar 파일이 복사되는 위치
ENV APP_HOME=/usr/app/ ENV APP_HOME=/usr/app/
# 작업 시작 위치 # 작업 시작 위치

View File

@@ -10,7 +10,7 @@ applications:
- egov-discovery-provided-service # discovery service binding - egov-discovery-provided-service # discovery service binding
env: env:
spring_profiles_active: cf spring_profiles_active: cf
spring_cloud_config_uri: https://egov-config.paas-ta.org spring_cloud_config_uri: http://localhost:8888
app_name: egov-reserve-request-service # logstash custom app name app_name: egov-reserve-request-service # logstash custom app name
TZ: Asia/Seoul TZ: Asia/Seoul
JAVA_OPTS: -Xss349k JAVA_OPTS: -Xss349k

View File

@@ -1,33 +1,33 @@
package org.egovframe.cloud.reserverequestservice; package org.egovframe.cloud.reserverequestservice;
import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient; import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.ComponentScan;
import reactor.blockhound.BlockHound; //import reactor.blockhound.BlockHound;
import java.security.Security; import java.security.Security;
@ComponentScan({"org.egovframe.cloud.common", "org.egovframe.cloud.reactive", "org.egovframe.cloud.reserverequestservice"}) // org.egovframe.cloud.common package 포함하기 위해 @ComponentScan({"org.egovframe.cloud.common", "org.egovframe.cloud.reactive", "org.egovframe.cloud.reserverequestservice"}) // org.egovframe.cloud.common package 포함하기 위해
@EnableDiscoveryClient @EnableDiscoveryClient
@SpringBootApplication @SpringBootApplication
public class ReserveRequestServiceApplication { public class ReserveRequestServiceApplication {
public static void main(String[] args) { public static void main(String[] args) {
// TLSv1/v1.1 No longer works after upgrade, "No appropriate protocol" error // TLSv1/v1.1 No longer works after upgrade, "No appropriate protocol" error
String property = Security.getProperty("jdk.tls.disabledAlgorithms").replace(", TLSv1", "").replace(", TLSv1.1", ""); String property = Security.getProperty("jdk.tls.disabledAlgorithms").replace(", TLSv1", "").replace(", TLSv1.1", "");
Security.setProperty("jdk.tls.disabledAlgorithms", property); Security.setProperty("jdk.tls.disabledAlgorithms", property);
//blocking 코드 감지 //blocking 코드 감지
BlockHound.builder() // BlockHound.builder()
//mysql r2dbc 에서 호출되는 FileInputStream.readBytes() 가 블로킹코드인데 이를 허용해주도록 한다. // //mysql r2dbc 에서 호출되는 FileInputStream.readBytes() 가 블로킹코드인데 이를 허용해주도록 한다.
//해당 코드가 어디서 호출되는지 알지 못하는 상태에서 FileInputStream.readBytes() 자체를 허용해주는 것은 좋지 않다. // //해당 코드가 어디서 호출되는지 알지 못하는 상태에서 FileInputStream.readBytes() 자체를 허용해주는 것은 좋지 않다.
// 누군가 무분별하게 사용하게 되면 검출해 낼 수ㅂ 없어 시스템의 위험요소로 남게 된다. // // 누군가 무분별하게 사용하게 되면 검출해 낼 수ㅂ 없어 시스템의 위험요소로 남게 된다.
// r2dbc를 사용하기 위해 해당 호출부분만 허용하고 나머지는 여전히 검출대상으로 남기도록 한다. // // r2dbc를 사용하기 위해 해당 호출부분만 허용하고 나머지는 여전히 검출대상으로 남기도록 한다.
.allowBlockingCallsInside("dev.miku.r2dbc.mysql.client.ReactorNettyClient", "init") // .allowBlockingCallsInside("dev.miku.r2dbc.mysql.client.ReactorNettyClient", "init")
.install(); // .install();
SpringApplication.run(ReserveRequestServiceApplication.class, args); SpringApplication.run(ReserveRequestServiceApplication.class, args);
} }
} }

View File

@@ -1,9 +1,8 @@
# openjdk8 base image # openjdk8 base image
FROM openjdk:8-jre-alpine FROM openjdk:8-jre-alpine
# config server uri: dockder run --e 로 변경 가능 # directory 생성
#ENV SPRING_CLOUD_CONFIG_URI https://egov-config.paas-ta.org RUN mkdir -p /usr/app/msa-attach-volume/messages
RUN mkdir -p /usr/app/msa-attach-volume
# jar 파일이 복사되는 위치 # jar 파일이 복사되는 위치
ENV APP_HOME=/usr/app/ ENV APP_HOME=/usr/app/
# 작업 시작 위치 # 작업 시작 위치
@@ -12,5 +11,5 @@ WORKDIR $APP_HOME
COPY build/libs/*.jar app.jar COPY build/libs/*.jar app.jar
# cf docker push, random port 사용할 수 없다 # cf docker push, random port 사용할 수 없다
#EXPOSE 80 #EXPOSE 80
# 실행 (application-cf.yml 프로필이 기본값) # 실행
CMD ["java", "-Dspring.profiles.active=${profile:cf}", "-jar", "app.jar"] CMD ["java", "-Dspring.profiles.active=${profile:default}", "-jar", "app.jar"]

View File

@@ -10,7 +10,7 @@ applications:
- egov-discovery-provided-service # discovery service binding - egov-discovery-provided-service # discovery service binding
env: env:
spring_profiles_active: cf spring_profiles_active: cf
spring_cloud_config_uri: https://egov-config.paas-ta.org spring_cloud_config_uri: http://localhost:8888
app_name: egov-user-service # logstash custom app name app_name: egov-user-service # logstash custom app name
TZ: Asia/Seoul TZ: Asia/Seoul
JAVA_OPTS: -Xss349k JAVA_OPTS: -Xss349k

View File

@@ -15,7 +15,7 @@
</springProfile> </springProfile>
<springProfile name="!default"> <springProfile name="!default">
<!-- java -Ddestination="localhost:5001" 와 같이 변경할 수 있다. cf 환경에서는 manifest.yml 파일에 환경변수로 추가 --> <!-- java -Ddestination="localhost:5001" 와 같이 변경할 수 있다. cf 환경에서는 manifest.yml 파일에 환경변수로 추가 -->
<property name="destination" value="${destination:-localhost:5001}" /> <property name="destination" value="${logstash_hostname:-localhost:5001}" />
<property name="app_name" value="${app_name:-user-service}" /> <property name="app_name" value="${app_name:-user-service}" />
<!-- ELK - Logstash 로 로그를 전송하기 위한 appender --> <!-- ELK - Logstash 로 로그를 전송하기 위한 appender -->

View File

@@ -12,16 +12,14 @@ eureka:
register-with-eureka: true # eureka 서버에 등록 register-with-eureka: true # eureka 서버에 등록
fetch-registry: true # 외부 검색 가능 fetch-registry: true # 외부 검색 가능
service-url: service-url:
defaultZone: http://admin:admin@localhost:8761/eureka defaultZone: http://admin:admin@${eureka.instance.hostname:localhost}:8761/eureka
# file attach location - messages{lang}.properties 도 이 경로에 위치한다. # file attach location - messages{lang}.properties 도 이 경로에 위치한다.
file: file:
directory: ${user.home}/msa-attach-volume # url 사용시에는 사용되지 않는다 directory: ${app.home:${user.home}}/msa-attach-volume # url 사용시에는 사용되지 않는다
url: http://localhost:8080 # nginx 로 파일 다운로드 처리 url: http://localhost:8080 # nginx 로 파일 다운로드 처리
messages: messages:
directory: ${file.directory}/messages directory: ${file.directory}/messages
logstash:
url: localhost:8086
apigateway: apigateway:
host: http://localhost:${server.port} host: http://localhost:${server.port}
@@ -29,12 +27,12 @@ apigateway:
# rabbitmq server # rabbitmq server
spring: spring:
rabbitmq: rabbitmq:
host: localhost host: ${rabbitmq.hostname:${localhost}}
port: 5672 port: 5672
username: guest username: guest
password: guest password: guest
zipkin: zipkin:
base-url: http://localhost:8085 base-url: http://${zipkin.hostname:${localhost}}:9411
egov: egov:
message: hello message: hello

View File

@@ -1,5 +1,5 @@
database: database:
url: jdbc:mysql://localhost:3306/msaportal url: jdbc:mysql://${mysql.hostname:localhost}:3306/msaportal
spring: spring:
datasource: datasource:

View File

@@ -1,5 +1,5 @@
database: database:
url: jdbc:mysql://localhost:3306/msaportal url: jdbc:mysql://${mysql.hostname:localhost}:3306/msaportal
spring: spring:
datasource: datasource:

View File

@@ -1,6 +1,6 @@
spring: spring:
r2dbc: r2dbc:
url: r2dbc:mysql://localhost:3306/reservation?serverTimezone=Asia/Seoul url: r2dbc:mysql://${mysql.hostname:localhost}:3306/reservation?serverTimezone=Asia/Seoul
username: msaportal username: msaportal
password: msaportal password: msaportal
cloud: cloud:

View File

@@ -1,6 +1,6 @@
spring: spring:
r2dbc: r2dbc:
url: r2dbc:mysql://localhost:3306/msaportal?serverTimezone=Asia/Seoul url: r2dbc:mysql://${mysql.hostname:localhost}:3306/msaportal?serverTimezone=Asia/Seoul
username: msaportal username: msaportal
password: msaportal password: msaportal
cloud: cloud:

View File

@@ -1,6 +1,6 @@
spring: spring:
r2dbc: r2dbc:
url: r2dbc:mysql://localhost:3306/reservation?serverTimezone=Asia/Seoul url: r2dbc:mysql://${mysql.hostname:localhost}:3306/reservation?serverTimezone=Asia/Seoul
username: msaportal username: msaportal
password: msaportal password: msaportal
cloud: cloud:

View File

@@ -1,5 +1,5 @@
database: database:
url: jdbc:mysql://localhost:3306/msaportal url: jdbc:mysql://${mysql.hostname:localhost}:3306/msaportal
spring: spring:
datasource: datasource:

View File

@@ -0,0 +1,116 @@
version: '3'
services:
rabbitmq:
container_name: rabbitmq
image: rabbitmq:management
ports:
- "5672:5672"
- "15672:15672"
restart: always
environment:
TZ: Asia/Seoul
zipkin:
container_name: zipkin
image: openzipkin/zipkin
ports:
- "9411:9411"
restart: always
environment:
TZ: Asia/Seoul
config:
container_name: config
image: egovframe/msa-edu-config:latest
ports:
- "8888:8888"
restart: always
volumes:
- ${HOME}/workspace.edu/egovframe-msa-edu/config:/usr/app/config # volume bind
environment:
ENCRYPT_KEY: token_secret
SPRING_PROFILES_ACTIVE: native
# logstash_hostname: logstash:5001
RABBITMQ_HOSTNAME: rabbitmq
ZIPKIN_HOSTNAME: zipkin
TZ: Asia/Seoul
discovery:
container_name: discovery
image: egovframe/msa-discovery:latest
ports:
- "8761:8761"
restart: always
environment:
SPRING_PROFILES_ACTIVE: default
EUREKA_INSTANCE_HOSTNAME: discovery
TZ: Asia/Seoul
apigateway:
container_name: apigateway
image: egovframe/msa-apigateway:latest
ports:
- "8000:8000"
restart: on-failure
volumes:
- ${HOME}/workspace:/usr/app/msa-attach-volume
environment:
SPRING_CLOUD_CONFIG_URI: http://config:8888
SPRING_PROFILES_ACTIVE: default
EUREKA_INSTANCE_HOSTNAME: discovery
RABBITMQ_HOSTNAME: rabbitmq
ZIPKIN_HOSTNAME: zipkin
APP_HOME: /usr/app
TZ: Asia/Seoul
userservice:
container_name: userservice
image: egovframe/msa-user-service:latest
restart: always
volumes:
- ${HOME}/workspace.edu/docker-compose:/usr/app/msa-attach-volume
environment:
SPRING_CLOUD_CONFIG_URI: http://config:8888
SPRING_PROFILES_ACTIVE: default
APP_HOME: /usr/app
# logstash_hostname: logstash:5001
EUREKA_INSTANCE_HOSTNAME: discovery
MYSQL_HOSTNAME: mysql
RABBITMQ_HOSTNAME: rabbitmq
ZIPKIN_HOSTNAME: zipkin
TZ: Asia/Seoul
boardservice:
container_name: boardservice
image: egovframe/msa-board-service:latest
restart: always
volumes:
- ${HOME}/workspace:/usr/app/msa-attach-volume
environment:
SPRING_CLOUD_CONFIG_URI: http://config:8888
SPRING_PROFILES_ACTIVE: default
EUREKA_INSTANCE_HOSTNAME: discovery
APP_HOME: /usr/app
# logstash_hostname: logstash:5001
MYSQL_HOSTNAME: mysql
TZ: Asia/Seoul
portalservice:
container_name: portalservice
image: egovframe/msa-portal-service:latest
restart: always
volumes:
- ${HOME}/workspace:/usr/app/msa-attach-volume
environment:
SPRING_CLOUD_CONFIG_URI: http://config:8888
SPRING_PROFILES_ACTIVE: default
EUREKA_INSTANCE_HOSTNAME: discovery
APP_HOME: /usr/app
# logstash_hostname: logstash:5001
MYSQL_HOSTNAME: mysql
TZ: Asia/Seoul
networks:
default:
external:
name: egov-network

View File

@@ -0,0 +1,70 @@
version: '3'
services:
config:
container_name: config
image: egovframe/msa-edu-config:latest
ports:
- "8888:8888"
restart: always
volumes:
- ${HOME}/workspace.edu/egovframe-msa-edu/config:/usr/app/config # volume bind
environment:
ENCRYPT_KEY: token_secret
logstash_hostname: logstash:5001
RABBITMQ_HOSTNAME: rabbitmq
ZIPKIN_HOSTNAME: zipkin
TZ: Asia/Seoul
discovery:
container_name: discovery
image: egovframe/msa-discovery:latest
ports:
- "8761:8761"
restart: always
environment:
SPRING_PROFILES_ACTIVE: default
EUREKA_INSTANCE_HOSTNAME: discovery
TZ: Asia/Seoul
apigateway:
container_name: apigateway
image: egovframe/msa-apigateway:latest
ports:
- "8000:8000"
restart: on-failure
volumes:
- ${HOME}/workspace:/usr/app/msa-attach-volume
environment:
SPRING_CLOUD_CONFIG_URI: http://config:8888
SPRING_PROFILES_ACTIVE: default
EUREKA_INSTANCE_HOSTNAME: discovery
RABBITMQ_HOSTNAME: rabbitmq
ZIPKIN_HOSTNAME: zipkin
APP_HOME: /usr/app
TZ: Asia/Seoul
depends_on:
- config
rabbitmq:
container_name: rabbitmq
image: rabbitmq:management
ports:
- "5672:5672"
- "15672:15672"
restart: always
environment:
TZ: Asia/Seoul
zipkin:
container_name: zipkin
image: openzipkin/zipkin
ports:
- "9411:9411"
restart: always
environment:
TZ: Asia/Seoul
networks:
default:
external:
name: egov-network

View File

@@ -0,0 +1,53 @@
version: '3'
services:
userservice:
container_name: userservice
image: egovframe/msa-user-service:latest
restart: always
volumes:
- ${HOME}/workspace:/usr/app/msa-attach-volume
environment:
SPRING_CLOUD_CONFIG_URI: http://config:8888
SPRING_PROFILES_ACTIVE: default
APP_HOME: /usr/app
logstash_hostname: logstash:5001
EUREKA_INSTANCE_HOSTNAME: discovery
MYSQL_HOSTNAME: mysql
RABBITMQ_HOSTNAME: rabbitmq
ZIPKIN_HOSTNAME: zipkin
TZ: Asia/Seoul
boardservice:
container_name: boardservice
image: egovframe/msa-board-service:latest
restart: always
volumes:
- ${HOME}/workspace:/usr/app/msa-attach-volume
environment:
SPRING_CLOUD_CONFIG_URI: http://config:8888
SPRING_PROFILES_ACTIVE: default
EUREKA_INSTANCE_HOSTNAME: discovery
APP_HOME: /usr/app
logstash_hostname: logstash:5001
MYSQL_HOSTNAME: mysql
TZ: Asia/Seoul
portalservice:
container_name: portalservice
image: egovframe/msa-portal-service:latest
restart: always
volumes:
- ${HOME}/workspace:/usr/app/msa-attach-volume
environment:
SPRING_CLOUD_CONFIG_URI: http://config:8888
SPRING_PROFILES_ACTIVE: default
EUREKA_INSTANCE_HOSTNAME: discovery
APP_HOME: /usr/app
logstash_hostname: logstash:5001
MYSQL_HOSTNAME: mysql
TZ: Asia/Seoul
networks:
default:
external:
name: egov-network

View File

@@ -14,10 +14,8 @@ services:
memlock: memlock:
soft: -1 soft: -1
hard: -1 hard: -1
networks:
- elastic
volumes: volumes:
- ${HOME}/docker-volume/elasticsearch/data:/usr/share/elasticsearch/data - ${HOME}/workspace.edu/data:/usr/share/elasticsearch/data
logstash: logstash:
container_name: logstash container_name: logstash
@@ -37,10 +35,6 @@ services:
source: ${PWD}/logstash/pipeline source: ${PWD}/logstash/pipeline
target: /usr/share/logstash/pipeline target: /usr/share/logstash/pipeline
read_only: true read_only: true
networks:
- elastic
depends_on:
- elasticsearch
kibana: kibana:
container_name: kibana container_name: kibana
@@ -57,11 +51,8 @@ services:
source: ${PWD}/kibana/config/kibana.yml source: ${PWD}/kibana/config/kibana.yml
target: /usr/share/kibana/config/kibana.yml target: /usr/share/kibana/config/kibana.yml
read_only: true read_only: true
networks:
- elastic
depends_on:
- elasticsearch
networks: networks:
elastic: default:
driver: bridge external:
name: egov-network

View File

@@ -17,3 +17,8 @@ services:
ports: ports:
- "3306:3306" - "3306:3306"
container_name: mysql container_name: mysql
networks:
default:
external:
name: egov-network

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,5 +1,19 @@
-- reserve Table Create SQL
CREATE TABLE IF NOT EXISTS reserve /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8 */;
/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
/*!40103 SET TIME_ZONE='+00:00' */;
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
DROP TABLE IF EXISTS `reserve`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE IF NOT EXISTS `reserve`
( (
`reserve_id` VARCHAR(255) NOT NULL COMMENT '예약 id', `reserve_id` VARCHAR(255) NOT NULL COMMENT '예약 id',
`reserve_item_id` BIGINT NULL COMMENT '예약 물품 id', `reserve_item_id` BIGINT NULL COMMENT '예약 물품 id',
@@ -20,7 +34,6 @@ CREATE TABLE IF NOT EXISTS reserve
`modified_date` DATETIME NULL COMMENT '수정일', `modified_date` DATETIME NULL COMMENT '수정일',
`last_modified_by` VARCHAR(255) NULL COMMENT '수정자', `last_modified_by` VARCHAR(255) NULL COMMENT '수정자',
PRIMARY KEY (reserve_id) PRIMARY KEY (reserve_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='예약 신청&확인';
/*!40101 SET character_set_client = @saved_cs_client */;
ALTER TABLE reserve COMMENT '예약 신청&확인';

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB