diff --git a/.gitignore b/.gitignore index 3045994..6b140be 100644 --- a/.gitignore +++ b/.gitignore @@ -43,3 +43,35 @@ HELP.md *.DS_Store *.AppleDouble *.LSOverride + + +# dependencies +**/node_modules +**/.pnp +**/.pnp.js + +# testing +**/coverage + +# next.js +**/.next/ +**/out/ + +# production +**/build +**/dist + +# misc +**.DS_Store +*.pem + +# debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# local env files +**/.env.local +**/.env.development.local +**/.env.test.local +**/.env.production.local \ No newline at end of file diff --git a/backend/config/src/main/resources/logback-spring.xml b/backend/config/src/main/resources/logback-spring.xml index d3d82ad..28c2059 100644 --- a/backend/config/src/main/resources/logback-spring.xml +++ b/backend/config/src/main/resources/logback-spring.xml @@ -8,12 +8,12 @@ - + - + diff --git a/backend/reserve-check-service/build.gradle b/backend/reserve-check-service/build.gradle index 8403626..5e05b18 100644 --- a/backend/reserve-check-service/build.gradle +++ b/backend/reserve-check-service/build.gradle @@ -44,7 +44,7 @@ dependencies { //messaging implementation 'org.springframework.cloud:spring-cloud-stream' implementation 'org.springframework.cloud:spring-cloud-stream-binder-rabbit' - implementation 'net.java.dev.jna:jna:5.9.0' // byte-buddy (No compatible attachment provider is available.) +// implementation 'net.java.dev.jna:jna:5.9.0' // byte-buddy (No compatible attachment provider is available.) implementation 'io.jsonwebtoken:jjwt:0.9.1' @@ -55,8 +55,8 @@ dependencies { implementation 'org.springdoc:springdoc-openapi-webflux-ui:1.5.10' // bolcking 호출 감지 - implementation 'io.projectreactor:reactor-tools:3.4.9' - implementation 'io.projectreactor.tools:blockhound:1.0.6.RELEASE' +// implementation 'io.projectreactor:reactor-tools:3.4.9' +// implementation 'io.projectreactor.tools:blockhound:1.0.6.RELEASE' //lombok implementation 'org.projectlombok:lombok' diff --git a/backend/reserve-check-service/src/main/java/org/egovframe/cloud/reservechecksevice/client/dto/UserResponseDto.java b/backend/reserve-check-service/src/main/java/org/egovframe/cloud/reservechecksevice/client/dto/UserResponseDto.java index 3eb78c1..30daa50 100644 --- a/backend/reserve-check-service/src/main/java/org/egovframe/cloud/reservechecksevice/client/dto/UserResponseDto.java +++ b/backend/reserve-check-service/src/main/java/org/egovframe/cloud/reservechecksevice/client/dto/UserResponseDto.java @@ -2,6 +2,7 @@ package org.egovframe.cloud.reservechecksevice.client.dto; import lombok.Builder; import lombok.Getter; +import lombok.NoArgsConstructor; /** * org.egovframe.cloud.userservice.api.user.dto.UserResponseDto @@ -21,6 +22,7 @@ import lombok.Getter; * */ @Getter +@NoArgsConstructor public class UserResponseDto { private String userId; diff --git a/backend/reserve-item-service/build.gradle b/backend/reserve-item-service/build.gradle index 6ed4ec5..be6c424 100644 --- a/backend/reserve-item-service/build.gradle +++ b/backend/reserve-item-service/build.gradle @@ -50,13 +50,13 @@ dependencies { implementation 'org.springdoc:springdoc-openapi-webflux-ui:1.5.10' // bolcking 호출 감지 - implementation 'io.projectreactor:reactor-tools:3.4.9' - implementation 'io.projectreactor.tools:blockhound:1.0.6.RELEASE' +// implementation 'io.projectreactor:reactor-tools:3.4.9' +// implementation 'io.projectreactor.tools:blockhound:1.0.6.RELEASE' //messaging implementation 'org.springframework.cloud:spring-cloud-stream' implementation 'org.springframework.cloud:spring-cloud-stream-binder-rabbit' - implementation 'net.java.dev.jna:jna:5.9.0' // byte-buddy (No compatible attachment provider is available.) +// implementation 'net.java.dev.jna:jna:5.9.0' // byte-buddy (No compatible attachment provider is available.) //lombok implementation 'org.projectlombok:lombok' diff --git a/backend/reserve-request-service/build.gradle b/backend/reserve-request-service/build.gradle index f109d83..6da21ab 100644 --- a/backend/reserve-request-service/build.gradle +++ b/backend/reserve-request-service/build.gradle @@ -46,7 +46,7 @@ dependencies { implementation 'org.springframework.cloud:spring-cloud-stream' implementation 'org.springframework.cloud:spring-cloud-stream-binder-rabbit' implementation 'org.springframework.boot:spring-boot-starter-amqp' - implementation 'net.java.dev.jna:jna:5.9.0' // byte-buddy (No compatible attachment provider is available.) +// implementation 'net.java.dev.jna:jna:5.9.0' // byte-buddy (No compatible attachment provider is available.) implementation 'io.jsonwebtoken:jjwt:0.9.1' @@ -58,8 +58,8 @@ dependencies { implementation 'org.springdoc:springdoc-openapi-webflux-ui:1.5.10' // bolcking 호출 감지 - implementation 'io.projectreactor:reactor-tools:3.4.9' - implementation 'io.projectreactor.tools:blockhound:1.0.6.RELEASE' +// implementation 'io.projectreactor:reactor-tools:3.4.9' +// implementation 'io.projectreactor.tools:blockhound:1.0.6.RELEASE' //lombok implementation 'org.projectlombok:lombok' diff --git a/backend/reserve-request-service/src/test/java/org/egovframe/cloud/reserverequestservice/api/ReserveApiControllerTest.java b/backend/reserve-request-service/src/test/java/org/egovframe/cloud/reserverequestservice/api/ReserveApiControllerTest.java new file mode 100644 index 0000000..935a53c --- /dev/null +++ b/backend/reserve-request-service/src/test/java/org/egovframe/cloud/reserverequestservice/api/ReserveApiControllerTest.java @@ -0,0 +1,85 @@ +package org.egovframe.cloud.reserverequestservice.api; + +import static org.assertj.core.api.Assertions.*; + +import java.time.LocalDateTime; + +import org.egovframe.cloud.common.domain.Role; +import org.egovframe.cloud.reserverequestservice.api.dto.ReserveResponseDto; +import org.egovframe.cloud.reserverequestservice.api.dto.ReserveSaveRequestDto; +import org.egovframe.cloud.reserverequestservice.config.WithCustomMockUser; +import org.egovframe.cloud.reserverequestservice.domain.Reserve; +import org.egovframe.cloud.reserverequestservice.domain.ReserveRepository; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.web.reactive.server.WebTestClient; + +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +@EnableConfigurationProperties +@TestPropertySource(properties = {"spring.config.location=classpath:application-test.yml"}) +@ActiveProfiles(profiles = "test") +class ReserveApiControllerTest { + + @Autowired + private ReserveRepository reserveRepository; + + @Autowired + private WebTestClient webTestClient; + + private Reserve reserve; + + @BeforeEach + public void setup() { + + reserve = Reserve.builder() + .reserveId("1") + .reserveQty(50) + .reservePurposeContent("test") + .reserveStatusId("request") + .reserveStartDate(LocalDateTime.of(2021, 9, 9, 1, 1)) + .reserveEndDate(LocalDateTime.of(2021, 9, 20, 1, 1)) + .build(); + } + + @AfterEach + public void tearDown() { + reserveRepository.deleteAll().block(); + } + + @Test + @WithCustomMockUser(userId = "user", role = Role.USER) + public void 사용자_예약_성공() throws Exception { + + ReserveSaveRequestDto saveRequestDto = + ReserveSaveRequestDto.builder() + .reserveItemId(reserve.getReserveItemId()) + .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(); + + ReserveResponseDto responseBody = webTestClient.post() + .uri("/api/v1/requests/evaluates") + .bodyValue(saveRequestDto) + .exchange() + .expectStatus().isCreated() + .expectBody(ReserveResponseDto.class) + .returnResult().getResponseBody(); + + assertThat(responseBody.getReserveQty()).isEqualTo(reserve.getReserveQty()); + assertThat(responseBody.getReservePurposeContent()).isEqualTo(reserve.getReservePurposeContent()); + + } + +} \ No newline at end of file diff --git a/backend/reserve-request-service/src/test/java/org/egovframe/cloud/reserverequestservice/config/R2dbcConfig.java b/backend/reserve-request-service/src/test/java/org/egovframe/cloud/reserverequestservice/config/R2dbcConfig.java new file mode 100644 index 0000000..0744407 --- /dev/null +++ b/backend/reserve-request-service/src/test/java/org/egovframe/cloud/reserverequestservice/config/R2dbcConfig.java @@ -0,0 +1,40 @@ +package org.egovframe.cloud.reserverequestservice.config; + +import org.springframework.boot.test.context.TestConfiguration; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Profile; +import org.springframework.core.io.ClassPathResource; +import org.springframework.data.r2dbc.repository.config.EnableR2dbcRepositories; +import org.springframework.r2dbc.connection.init.CompositeDatabasePopulator; +import org.springframework.r2dbc.connection.init.ConnectionFactoryInitializer; +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") +@TestConfiguration +@EnableR2dbcRepositories +public class R2dbcConfig { + @Bean + public H2ConnectionFactory connectionFactory() { + return new H2ConnectionFactory(H2ConnectionConfiguration.builder() + .inMemory("testdb") + .property(H2ConnectionOption.DB_CLOSE_DELAY, "-1") + .username("sa") + .build()); + } + + @Bean + public ConnectionFactoryInitializer initializer(ConnectionFactory connectionFactory) { + ConnectionFactoryInitializer initializer = new ConnectionFactoryInitializer(); + initializer.setConnectionFactory(connectionFactory); + CompositeDatabasePopulator populator = new CompositeDatabasePopulator(); + populator.addPopulators(new ResourceDatabasePopulator(new ClassPathResource("schema-h2.sql"))); + initializer.setDatabasePopulator(populator); + + return initializer; + } +} diff --git a/backend/reserve-request-service/src/test/java/org/egovframe/cloud/reserverequestservice/config/WithCustomMockUser.java b/backend/reserve-request-service/src/test/java/org/egovframe/cloud/reserverequestservice/config/WithCustomMockUser.java new file mode 100644 index 0000000..1ea0757 --- /dev/null +++ b/backend/reserve-request-service/src/test/java/org/egovframe/cloud/reserverequestservice/config/WithCustomMockUser.java @@ -0,0 +1,16 @@ +package org.egovframe.cloud.reserverequestservice.config; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +import org.egovframe.cloud.common.domain.Role; +import org.springframework.security.test.context.support.WithSecurityContext; + +@Retention(RetentionPolicy.RUNTIME) +@WithSecurityContext(factory = WithMockCustomUserSecurityContextFactory.class) +public @interface WithCustomMockUser { + + String userId() default "user"; + Role role() default Role.ADMIN; + +} diff --git a/backend/reserve-request-service/src/test/java/org/egovframe/cloud/reserverequestservice/config/WithMockCustomUserSecurityContextFactory.java b/backend/reserve-request-service/src/test/java/org/egovframe/cloud/reserverequestservice/config/WithMockCustomUserSecurityContextFactory.java new file mode 100644 index 0000000..b6f58a6 --- /dev/null +++ b/backend/reserve-request-service/src/test/java/org/egovframe/cloud/reserverequestservice/config/WithMockCustomUserSecurityContextFactory.java @@ -0,0 +1,25 @@ +package org.egovframe.cloud.reserverequestservice.config; + +import java.util.ArrayList; +import java.util.List; + +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.core.context.SecurityContext; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.test.context.support.WithSecurityContextFactory; + +public class WithMockCustomUserSecurityContextFactory implements WithSecurityContextFactory { + + @Override + public SecurityContext createSecurityContext(WithCustomMockUser mockUser) { + SecurityContext context = SecurityContextHolder.createEmptyContext(); + List roleList = new ArrayList<>(); + roleList.add(new SimpleGrantedAuthority(mockUser.role().getKey())); + UsernamePasswordAuthenticationToken authenticationToken = + new UsernamePasswordAuthenticationToken(mockUser.userId(), null, roleList); + context.setAuthentication(authenticationToken); + + return context; + } +} diff --git a/backend/reserve-request-service/src/test/resources/application-test.yml b/backend/reserve-request-service/src/test/resources/application-test.yml index e12cefb..837ca8e 100644 --- a/backend/reserve-request-service/src/test/resources/application-test.yml +++ b/backend/reserve-request-service/src/test/resources/application-test.yml @@ -1,21 +1,7 @@ spring: application: - name: reserve-request-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: console: enabled: true diff --git a/backend/reserve-request-service/src/test/resources/bootstrap.yml b/backend/reserve-request-service/src/test/resources/bootstrap.yml new file mode 100644 index 0000000..16d04da --- /dev/null +++ b/backend/reserve-request-service/src/test/resources/bootstrap.yml @@ -0,0 +1,5 @@ +spring: + cloud: + config: + uri: http://localhost:8888 + name: reserve-request-service \ No newline at end of file diff --git a/backend/reserve-request-service/src/test/resources/schema-h2.sql b/backend/reserve-request-service/src/test/resources/schema-h2.sql new file mode 100644 index 0000000..848e7c0 --- /dev/null +++ b/backend/reserve-request-service/src/test/resources/schema-h2.sql @@ -0,0 +1,23 @@ +-- reserve Table Create SQL +CREATE TABLE IF NOT EXISTS reserve +( + reserve_id VARCHAR(255) NOT 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_purpose_content VARCHAR(4000) NULL COMMENT '예약신청 목적', + attachment_code VARCHAR(255) NULL COMMENT '첨부파일 코드', + reserve_start_date DATETIME NULL COMMENT '예약 신청 시작일', + reserve_end_date DATETIME NULL COMMENT '예약 신청 종료일', + reserve_status_id VARCHAR(20) NULL COMMENT '예약상태 - 공통코드(reserve-status)', + reason_cancel_content VARCHAR(4000) NULL COMMENT '예약 취소 사유', + user_id VARCHAR(255) NULL COMMENT '예약자 id', + user_contact_no VARCHAR(50) NULL COMMENT '예약자 연락처', + user_email_addr VARCHAR(500) 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_id) +) ; diff --git a/config/application.yml b/config/application.yml index 3a3e5bf..2dc94de 100644 --- a/config/application.yml +++ b/config/application.yml @@ -27,12 +27,12 @@ apigateway: # rabbitmq server spring: rabbitmq: - host: ${rabbitmq.hostname:${localhost}} + host: ${rabbitmq.hostname:localhost} port: 5672 username: guest password: guest zipkin: - base-url: http://${zipkin.hostname:${localhost}}:9411 + base-url: http://${zipkin.hostname:localhost}:9411 egov: message: hello \ No newline at end of file diff --git a/config/reserve-item-service.yml b/config/reserve-item-service.yml index c14f1f6..e2c3bb1 100644 --- a/config/reserve-item-service.yml +++ b/config/reserve-item-service.yml @@ -3,14 +3,14 @@ spring: url: r2dbc:mysql://${mysql.hostname:localhost}:3306/msaportal?serverTimezone=Asia/Seoul username: msaportal password: msaportal -cloud: - stream: - function: - definition: reserveRequest # 예약 요청후 물품 재고업데이트 이벤트에 대한 consumer function - bindings: - reserveRequest-in-0: # 예약 요청후 물품 재고업데이트 이벤트에 대한 consumer binding - destination: reserve-request.topic # queue name - group: reserved - inventoryUpdated-out-0: # 예약 요청후 물품 재고업데이트 결과에 이벤트에 대한 supplier binding - destination: inventory-updated.topic # queue name - group: reserved + cloud: + stream: + function: + definition: reserveRequest # 예약 요청후 물품 재고업데이트 이벤트에 대한 consumer function + bindings: + reserveRequest-in-0: # 예약 요청후 물품 재고업데이트 이벤트에 대한 consumer binding + destination: reserve-request.topic # queue name + group: reserved + inventoryUpdated-out-0: # 예약 요청후 물품 재고업데이트 결과에 이벤트에 대한 supplier binding + destination: inventory-updated.topic # queue name + group: reserved diff --git a/config/reserve-request-service.yml b/config/reserve-request-service.yml index 8b6d989..a3bc2d5 100644 --- a/config/reserve-request-service.yml +++ b/config/reserve-request-service.yml @@ -3,14 +3,14 @@ spring: url: r2dbc:mysql://${mysql.hostname:localhost}:3306/reservation?serverTimezone=Asia/Seoul username: msaportal password: msaportal -cloud: - stream: - function: - definition: inventoryUpdated # 예약 요청후 물품 재고업데이트 결과에 이벤트에 대한 consumer function - bindings: - reserveRequest-out-0: # 예약 요청후 물품 재고업데이트 이벤트에 대한 supplier binding - destination: reserve-request.topic # queue name - group: reserved - inventoryUpdated-in-0: # 예약 요청후 물품 재고업데이트 결과에 이벤트에 대한 consumer binding - destination: inventory-updated.topic # queue name - group: reserved + cloud: + stream: + function: + definition: inventoryUpdated # 예약 요청후 물품 재고업데이트 결과에 이벤트에 대한 consumer function + bindings: + reserveRequest-out-0: # 예약 요청후 물품 재고업데이트 이벤트에 대한 supplier binding + destination: reserve-request.topic # queue name + group: reserved + inventoryUpdated-in-0: # 예약 요청후 물품 재고업데이트 결과에 이벤트에 대한 consumer binding + destination: inventory-updated.topic # queue name + group: reserved diff --git a/frontend/portal/package.json b/frontend/portal/package.json index 1e93fc1..acf54ff 100644 --- a/frontend/portal/package.json +++ b/frontend/portal/package.json @@ -8,8 +8,8 @@ }, "scripts": { "dev": "ts-node --project tsconfig.server.json server/index.ts", - "dev:sm": "SITE_ID=3 npm run dev", - "dev:lg": "SITE_ID=2 npm run dev", + "dev:sm": "set SITE_ID=3&&npm run dev", + "dev:lg": "set SITE_ID=2&&npm run dev", "build:server": "tsc --project tsconfig.server.json", "build:next": "next build", "prebuild": "rimraf ./build",