Initial commit
This commit is contained in:
@@ -0,0 +1,33 @@
|
||||
package org.egovframe.cloud.reserverequestservice;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import reactor.blockhound.BlockHound;
|
||||
|
||||
import java.security.Security;
|
||||
|
||||
@ComponentScan({"org.egovframe.cloud.common", "org.egovframe.cloud.reactive", "org.egovframe.cloud.reserverequestservice"}) // org.egovframe.cloud.common package 포함하기 위해
|
||||
@EnableDiscoveryClient
|
||||
@SpringBootApplication
|
||||
public class ReserveRequestServiceApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
// TLSv1/v1.1 No longer works after upgrade, "No appropriate protocol" error
|
||||
String property = Security.getProperty("jdk.tls.disabledAlgorithms").replace(", TLSv1", "").replace(", TLSv1.1", "");
|
||||
Security.setProperty("jdk.tls.disabledAlgorithms", property);
|
||||
|
||||
//blocking 코드 감지
|
||||
BlockHound.builder()
|
||||
//mysql r2dbc 에서 호출되는 FileInputStream.readBytes() 가 블로킹코드인데 이를 허용해주도록 한다.
|
||||
//해당 코드가 어디서 호출되는지 알지 못하는 상태에서 FileInputStream.readBytes() 자체를 허용해주는 것은 좋지 않다.
|
||||
// 누군가 무분별하게 사용하게 되면 검출해 낼 수ㅂ 없어 시스템의 위험요소로 남게 된다.
|
||||
// r2dbc를 사용하기 위해 해당 호출부분만 허용하고 나머지는 여전히 검출대상으로 남기도록 한다.
|
||||
.allowBlockingCallsInside("dev.miku.r2dbc.mysql.client.ReactorNettyClient", "init")
|
||||
.install();
|
||||
|
||||
SpringApplication.run(ReserveRequestServiceApplication.class, args);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,124 @@
|
||||
package org.egovframe.cloud.reserverequestservice.api;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.egovframe.cloud.reserverequestservice.api.dto.ReserveResponseDto;
|
||||
import org.egovframe.cloud.reserverequestservice.api.dto.ReserveSaveRequestDto;
|
||||
import org.egovframe.cloud.reserverequestservice.config.MessageListenerContainerFactory;
|
||||
import org.egovframe.cloud.reserverequestservice.domain.Category;
|
||||
import org.egovframe.cloud.reserverequestservice.service.ReserveService;
|
||||
import org.springframework.amqp.core.AmqpAdmin;
|
||||
import org.springframework.amqp.core.MessageListener;
|
||||
import org.springframework.amqp.rabbit.listener.MessageListenerContainer;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import java.time.Duration;
|
||||
|
||||
/**
|
||||
* org.egovframe.cloud.reserverequestservice.api.ReserveApiController
|
||||
*
|
||||
* 예약 신청 rest controller class
|
||||
*
|
||||
* @author 표준프레임워크센터 shinmj
|
||||
* @version 1.0
|
||||
* @since 2021/09/16
|
||||
*
|
||||
* <pre>
|
||||
* << 개정이력(Modification Information) >>
|
||||
*
|
||||
* 수정일 수정자 수정내용
|
||||
* ---------- -------- ---------------------------
|
||||
* 2021/09/16 shinmj 최초 생성
|
||||
* </pre>
|
||||
*/
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
@RestController
|
||||
public class ReserveApiController {
|
||||
|
||||
private final ReserveService reserveService;
|
||||
private final MessageListenerContainerFactory messageListenerContainerFactory;
|
||||
private final AmqpAdmin amqpAdmin;
|
||||
|
||||
/**
|
||||
* 예약 신청 - 심사
|
||||
*
|
||||
* @param saveRequestDtoMono
|
||||
* @return
|
||||
*/
|
||||
@PostMapping("/api/v1/requests/audit")
|
||||
@ResponseStatus(HttpStatus.CREATED)
|
||||
public Mono<ReserveResponseDto> create(@RequestBody Mono<ReserveSaveRequestDto> saveRequestDtoMono) {
|
||||
return saveRequestDtoMono.flatMap(reserveService::create);
|
||||
}
|
||||
|
||||
/**
|
||||
* 예약 신청 - 실시간
|
||||
*
|
||||
* @param saveRequestDtoMono
|
||||
* @return
|
||||
*/
|
||||
@PostMapping("/api/v1/requests")
|
||||
@ResponseStatus(HttpStatus.CREATED)
|
||||
public Mono<ReserveResponseDto> save(@RequestBody Mono<ReserveSaveRequestDto> saveRequestDtoMono) {
|
||||
return saveRequestDtoMono.flatMap(saveRequestDto -> {
|
||||
if (Category.EDUCATION.isEquals(saveRequestDto.getCategoryId())) {
|
||||
return reserveService.saveForEvent(saveRequestDto);
|
||||
}
|
||||
return reserveService.save(saveRequestDto);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 실시간 예약 신청 후 결과 여부 subscribe
|
||||
*
|
||||
* @param reserveId
|
||||
* @return
|
||||
*/
|
||||
@GetMapping(value = "/api/v1/requests/direct/{reserveId}", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
|
||||
public Flux<?> receiveReservationResult(@PathVariable String reserveId) {
|
||||
MessageListenerContainer mlc = messageListenerContainerFactory.createMessageListenerContainer(reserveId);
|
||||
Flux<String> f = Flux.create(emitter -> {
|
||||
mlc.setupMessageListener((MessageListener) m -> {
|
||||
String qname = m.getMessageProperties().getConsumerQueue();
|
||||
log.info("message received, queue={}", qname);
|
||||
|
||||
if (emitter.isCancelled()) {
|
||||
log.info("cancelled, queue={}", qname);
|
||||
mlc.stop();
|
||||
return;
|
||||
}
|
||||
|
||||
String payload = new String(m.getBody());
|
||||
log.info("message data = {}", payload);
|
||||
emitter.next(payload);
|
||||
|
||||
log.info("message sent to client, queue={}", qname);
|
||||
});
|
||||
|
||||
emitter.onRequest(v -> {
|
||||
log.info("starting container, queue={}", reserveId);
|
||||
mlc.start();
|
||||
});
|
||||
|
||||
emitter.onDispose(() -> {
|
||||
log.info("on dispose, queue={}", reserveId);
|
||||
mlc.stop();
|
||||
amqpAdmin.deleteQueue(reserveId);
|
||||
});
|
||||
|
||||
log.info("container started, queue={}", reserveId);
|
||||
});
|
||||
|
||||
return Flux.interval(Duration.ofSeconds(5))
|
||||
.map(v -> {
|
||||
log.info("sending keepalive message...");
|
||||
return "no news is good news";
|
||||
}).mergeWith(f);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
package org.egovframe.cloud.reserverequestservice.api.dto;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.ToString;
|
||||
import org.egovframe.cloud.reserverequestservice.domain.Reserve;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* org.egovframe.cloud.reserverequestservice.api.dto.ReserveResponseDto
|
||||
* <p>
|
||||
* 예약 신청 응답 dto class
|
||||
*
|
||||
* @author 표준프레임워크센터 shinmj
|
||||
* @version 1.0
|
||||
* @since 2021/09/17
|
||||
*
|
||||
* <pre>
|
||||
* << 개정이력(Modification Information) >>
|
||||
*
|
||||
* 수정일 수정자 수정내용
|
||||
* ---------- -------- ---------------------------
|
||||
* 2021/09/17 shinmj 최초 생성
|
||||
* </pre>
|
||||
*/
|
||||
@Getter
|
||||
@NoArgsConstructor
|
||||
@ToString
|
||||
public class ReserveResponseDto {
|
||||
|
||||
private String reserveId;
|
||||
|
||||
private Long reserveItemId;
|
||||
private Long locationId;
|
||||
private String categoryId;
|
||||
|
||||
private Integer reserveQty;
|
||||
private LocalDateTime reserveStartDate;
|
||||
private LocalDateTime reserveEndDate;
|
||||
private String reservePurposeContent;
|
||||
private String attachmentCode;
|
||||
|
||||
private String userId;
|
||||
private String userContactNo;
|
||||
private String userEmail;
|
||||
|
||||
@Builder
|
||||
public ReserveResponseDto(Reserve entity) {
|
||||
this.reserveId = entity.getReserveId();
|
||||
this.reserveItemId = entity.getReserveItemId();
|
||||
this.locationId = entity.getLocationId();
|
||||
this.categoryId = entity.getCategoryId();
|
||||
this.reserveQty = entity.getReserveQty();
|
||||
this.reserveStartDate = entity.getReserveStartDate();
|
||||
this.reserveEndDate = entity.getReserveEndDate();
|
||||
this.reservePurposeContent = entity.getReservePurposeContent();
|
||||
this.attachmentCode = entity.getAttachmentCode();
|
||||
this.userId = entity.getUserId();
|
||||
this.userContactNo = entity.getUserContactNo();
|
||||
this.userEmail = entity.getUserEmail();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
package org.egovframe.cloud.reserverequestservice.api.dto;
|
||||
|
||||
import lombok.*;
|
||||
import org.egovframe.cloud.reserverequestservice.domain.Reserve;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* org.egovframe.cloud.reserverequestservice.api.dto.ReserveSaveRequestDto
|
||||
* <p>
|
||||
* 예약 신청 저장 요청 dto class
|
||||
*
|
||||
* @author 표준프레임워크센터 shinmj
|
||||
* @version 1.0
|
||||
* @since 2021/09/17
|
||||
*
|
||||
* <pre>
|
||||
* << 개정이력(Modification Information) >>
|
||||
*
|
||||
* 수정일 수정자 수정내용
|
||||
* ---------- -------- ---------------------------
|
||||
* 2021/09/17 shinmj 최초 생성
|
||||
* </pre>
|
||||
*/
|
||||
@Getter
|
||||
@NoArgsConstructor
|
||||
@ToString
|
||||
public class ReserveSaveRequestDto {
|
||||
|
||||
@Setter
|
||||
private String reserveId;
|
||||
@NotNull
|
||||
private Long reserveItemId;
|
||||
private Long locationId;
|
||||
private String categoryId;
|
||||
private Integer totalQty;
|
||||
private String reserveMethodId;
|
||||
private String reserveMeansId;
|
||||
private LocalDateTime operationStartDate;
|
||||
private LocalDateTime operationEndDate;
|
||||
private LocalDateTime requestStartDate;
|
||||
private LocalDateTime requestEndDate;
|
||||
private Boolean isPeriod;
|
||||
private Integer periodMaxCount;
|
||||
|
||||
private Integer reserveQty; //예약 신청 인원/수량
|
||||
@NotNull
|
||||
private String reservePurposeContent; //예약 목적
|
||||
private String attachmentCode; //첨부파일 코드
|
||||
private LocalDateTime reserveStartDate; //예약 신청 시작일
|
||||
private LocalDateTime reserveEndDate; //예약 신청 종료일
|
||||
@Setter
|
||||
private String reserveStatusId; //예약상태 - 공통코드(reserve-status)
|
||||
@NotNull
|
||||
private String userId; //예약자
|
||||
@NotNull
|
||||
private String userContactNo; //예약자 연락처
|
||||
@NotNull
|
||||
private String userEmail; //예약자 이메일
|
||||
|
||||
@Builder
|
||||
public ReserveSaveRequestDto(String reserveId, Long reserveItemId, Long locationId, String categoryId,
|
||||
Integer totalQty, String reserveMethodId, String reserveMeansId, LocalDateTime operationStartDate,
|
||||
LocalDateTime operationEndDate, LocalDateTime requestStartDate, LocalDateTime requestEndDate,
|
||||
Boolean isPeriod, Integer periodMaxCount, Integer reserveQty, String reservePurposeContent,
|
||||
String attachmentCode, LocalDateTime reserveStartDate, LocalDateTime reserveEndDate,
|
||||
String reserveStatusId, String userId, String userContactNo, String userEmail) {
|
||||
this.reserveId = reserveId;
|
||||
this.reserveItemId = reserveItemId;
|
||||
this.locationId = locationId;
|
||||
this.categoryId = categoryId;
|
||||
this.totalQty = totalQty;
|
||||
this.reserveMethodId = reserveMethodId;
|
||||
this.reserveMeansId = reserveMeansId;
|
||||
this.operationStartDate = operationStartDate;
|
||||
this.operationEndDate = operationEndDate;
|
||||
this.requestStartDate = requestStartDate;
|
||||
this.requestEndDate = requestEndDate;
|
||||
this.isPeriod = isPeriod;
|
||||
this.periodMaxCount = periodMaxCount;
|
||||
this.reserveQty = reserveQty;
|
||||
this.reservePurposeContent = reservePurposeContent;
|
||||
this.attachmentCode = attachmentCode;
|
||||
this.reserveStartDate = reserveStartDate;
|
||||
this.reserveEndDate = reserveEndDate;
|
||||
this.reserveStatusId = reserveStatusId;
|
||||
this.userId = userId;
|
||||
this.userContactNo = userContactNo;
|
||||
this.userEmail = userEmail;
|
||||
}
|
||||
|
||||
public Reserve toEntity() {
|
||||
return Reserve.builder()
|
||||
.reserveId(this.reserveId)
|
||||
.reserveItemId(this.reserveItemId)
|
||||
.locationId(this.locationId)
|
||||
.categoryId(this.categoryId)
|
||||
.reserveQty(this.reserveQty)
|
||||
.reservePurposeContent(this.reservePurposeContent)
|
||||
.attachmentCode(this.attachmentCode)
|
||||
.reserveStartDate(this.reserveStartDate)
|
||||
.reserveEndDate(this.reserveEndDate)
|
||||
.reserveStatusId(this.reserveStatusId)
|
||||
.userId(this.userId)
|
||||
.userContactNo(this.userContactNo)
|
||||
.userEmail(this.userEmail)
|
||||
.build();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package org.egovframe.cloud.reserverequestservice.config;
|
||||
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.amqp.core.AcknowledgeMode;
|
||||
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
|
||||
import org.springframework.amqp.rabbit.listener.MessageListenerContainer;
|
||||
import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* org.egovframe.cloud.reserverequestservice.config.MessageListenerContainerFactory
|
||||
*
|
||||
* 동적으로 이벤트 큐 생성하기 위한 component
|
||||
*
|
||||
* @author 표준프레임워크센터 shinmj
|
||||
* @version 1.0
|
||||
* @since 2021/09/30
|
||||
*
|
||||
* <pre>
|
||||
* << 개정이력(Modification Information) >>
|
||||
*
|
||||
* 수정일 수정자 수정내용
|
||||
* ---------- -------- ---------------------------
|
||||
* 2021/09/30 shinmj 최초 생성
|
||||
* </pre>
|
||||
*/
|
||||
@NoArgsConstructor
|
||||
@Component
|
||||
public class MessageListenerContainerFactory {
|
||||
|
||||
@Autowired
|
||||
private ConnectionFactory connectionFactory;
|
||||
|
||||
public MessageListenerContainer createMessageListenerContainer(String queueName) {
|
||||
SimpleMessageListenerContainer mlc = new SimpleMessageListenerContainer();
|
||||
mlc.setConnectionFactory(connectionFactory);
|
||||
mlc.addQueueNames(queueName);
|
||||
mlc.setAcknowledgeMode(AcknowledgeMode.AUTO);
|
||||
|
||||
return mlc;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package org.egovframe.cloud.reserverequestservice.config;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.ToString;
|
||||
|
||||
/**
|
||||
* org.egovframe.cloud.reserverequestservice.config.RequestMessage
|
||||
*
|
||||
* 예약 신청 후 이벤트 스트림 message VO class
|
||||
*
|
||||
* @author 표준프레임워크센터 shinmj
|
||||
* @version 1.0
|
||||
* @since 2021/09/16
|
||||
*
|
||||
* <pre>
|
||||
* << 개정이력(Modification Information) >>
|
||||
*
|
||||
* 수정일 수정자 수정내용
|
||||
* ---------- -------- ---------------------------
|
||||
* 2021/09/16 shinmj 최초 생성
|
||||
* </pre>
|
||||
*/
|
||||
@NoArgsConstructor
|
||||
@Getter
|
||||
@ToString
|
||||
public class RequestMessage {
|
||||
private String reserveId;
|
||||
private Boolean isItemUpdated;
|
||||
|
||||
@Builder
|
||||
public RequestMessage(String reserveId, Boolean isItemUpdated) {
|
||||
this.reserveId = reserveId;
|
||||
this.isItemUpdated = isItemUpdated;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
package org.egovframe.cloud.reserverequestservice.config;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.egovframe.cloud.common.config.GlobalConstant;
|
||||
import org.egovframe.cloud.reserverequestservice.domain.ReserveStatus;
|
||||
import org.egovframe.cloud.reserverequestservice.service.ReserveService;
|
||||
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
|
||||
import org.springframework.amqp.rabbit.core.RabbitTemplate;
|
||||
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.messaging.Message;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* org.egovframe.cloud.reserverequestservice.config.ReserveEventConfig
|
||||
*
|
||||
* event stream 설정 class
|
||||
*
|
||||
* @author 표준프레임워크센터 shinmj
|
||||
* @version 1.0
|
||||
* @since 2021/09/16
|
||||
*
|
||||
* <pre>
|
||||
* << 개정이력(Modification Information) >>
|
||||
*
|
||||
* 수정일 수정자 수정내용
|
||||
* ---------- -------- ---------------------------
|
||||
* 2021/09/16 shinmj 최초 생성
|
||||
* </pre>
|
||||
*/
|
||||
@Slf4j
|
||||
@Configuration
|
||||
public class ReserveEventConfig {
|
||||
@Autowired
|
||||
private ReserveService reserveService;
|
||||
@Autowired
|
||||
private ConnectionFactory connectionFactory;
|
||||
|
||||
/**
|
||||
* 예약 신청(실시간) 후 재고 변경에 대한 성공 여부 consumer function
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Bean
|
||||
public Consumer<Message<RequestMessage>> inventoryUpdated() {
|
||||
return message -> {
|
||||
log.info("receive message: {}, headers: {}", message.getPayload(), message.getHeaders());
|
||||
if (message.getPayload().getIsItemUpdated()) {
|
||||
reserveService.updateStatus(message.getPayload().getReserveId(), ReserveStatus.APPROVE).subscribe();
|
||||
}else {
|
||||
reserveService.delete(message.getPayload().getReserveId()).subscribe();
|
||||
}
|
||||
|
||||
RabbitTemplate rabbitTemplate = rabbitTemplate(connectionFactory);
|
||||
rabbitTemplate.convertAndSend(GlobalConstant.SUCCESS_OR_NOT_EX_NAME,
|
||||
message.getPayload().getReserveId(), message.getPayload().getIsItemUpdated());
|
||||
};
|
||||
}
|
||||
|
||||
@Bean
|
||||
public RabbitTemplate rabbitTemplate(final ConnectionFactory connectionFactory) {
|
||||
final RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);
|
||||
rabbitTemplate.setMessageConverter(messageConverter());
|
||||
return rabbitTemplate;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public Jackson2JsonMessageConverter messageConverter() {
|
||||
return new Jackson2JsonMessageConverter();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package org.egovframe.cloud.reserverequestservice.domain;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
@Getter
|
||||
@RequiredArgsConstructor
|
||||
public enum Category {
|
||||
EDUCATION("education", "교육"),
|
||||
EQUIPMENT("equipment", "장비"),
|
||||
SPACE("space", "공간");
|
||||
|
||||
private final String key;
|
||||
private final String title;
|
||||
|
||||
public boolean isEquals(String compare) {
|
||||
return this.getKey().equals(compare);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
package org.egovframe.cloud.reserverequestservice.domain;
|
||||
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.ToString;
|
||||
import org.egovframe.cloud.reactive.domain.BaseEntity;
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.relational.core.mapping.Column;
|
||||
import org.springframework.data.relational.core.mapping.Table;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* org.egovframe.cloud.reserverequestservice.domain.Reserve
|
||||
*
|
||||
* 예약 도메인 클래스
|
||||
*
|
||||
* @author 표준프레임워크센터 shinmj
|
||||
* @version 1.0
|
||||
* @since 2021/09/15
|
||||
*
|
||||
* <pre>
|
||||
* << 개정이력(Modification Information) >>
|
||||
*
|
||||
* 수정일 수정자 수정내용
|
||||
* ---------- -------- ---------------------------
|
||||
* 2021/09/15 shinmj 최초 생성
|
||||
* </pre>
|
||||
*/
|
||||
@Getter
|
||||
@NoArgsConstructor
|
||||
@ToString
|
||||
@Table("reserve")
|
||||
public class Reserve extends BaseEntity {
|
||||
|
||||
@Id
|
||||
@Column
|
||||
private String reserveId; //예약 id
|
||||
|
||||
@Column
|
||||
private Long reserveItemId; //예약 물품 id
|
||||
|
||||
@Column
|
||||
private Long locationId; //예약 물품 - 지역 id
|
||||
|
||||
@Column
|
||||
private String categoryId; //예약 물품 - 유형 id
|
||||
|
||||
@Column
|
||||
private Integer reserveQty; //예약 신청 인원/수량
|
||||
|
||||
@Column
|
||||
private String reservePurposeContent; //예약 목적
|
||||
|
||||
@Column
|
||||
private String attachmentCode; //첨부파일 코드
|
||||
|
||||
@Column
|
||||
private LocalDateTime reserveStartDate; //예약 신청 시작일
|
||||
@Column
|
||||
private LocalDateTime reserveEndDate; //예약 신청 종료일
|
||||
|
||||
@Column
|
||||
private String reserveStatusId; //예약상태 - 공통코드(reserve-status)
|
||||
|
||||
@Column
|
||||
private String userId; //예약자
|
||||
|
||||
@Column
|
||||
private String userContactNo; //예약자 연락처
|
||||
|
||||
@Column("user_email_addr")
|
||||
private String userEmail; //예약자 이메일
|
||||
|
||||
@Builder
|
||||
public Reserve(String reserveId, Long reserveItemId, Long locationId, String categoryId, Integer reserveQty, String reservePurposeContent, String attachmentCode, LocalDateTime reserveStartDate, LocalDateTime reserveEndDate, String reserveStatusId, String userId, String userContactNo, String userEmail) {
|
||||
this.reserveId = reserveId;
|
||||
this.reserveItemId = reserveItemId;
|
||||
this.locationId = locationId;
|
||||
this.categoryId = categoryId;
|
||||
this.reserveQty = reserveQty;
|
||||
this.reservePurposeContent = reservePurposeContent;
|
||||
this.attachmentCode = attachmentCode;
|
||||
this.reserveStartDate = reserveStartDate;
|
||||
this.reserveEndDate = reserveEndDate;
|
||||
this.reserveStatusId = reserveStatusId;
|
||||
this.userId = userId;
|
||||
this.userContactNo = userContactNo;
|
||||
this.userEmail = userEmail;
|
||||
}
|
||||
|
||||
/**
|
||||
* 예약 상태 업데이트
|
||||
*
|
||||
* @param reserveStatusId
|
||||
* @return
|
||||
*/
|
||||
public Reserve updateStatus(String reserveStatusId) {
|
||||
this.reserveStatusId = reserveStatusId;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* create 정보 세팅
|
||||
* insert 시 필요
|
||||
*
|
||||
* @param createdDate
|
||||
* @param createdBy
|
||||
* @return
|
||||
*/
|
||||
public Reserve setCreatedInfo(LocalDateTime createdDate, String createdBy) {
|
||||
this.createdBy = createdBy;
|
||||
this.createDate = createdDate;
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package org.egovframe.cloud.reserverequestservice.domain;
|
||||
|
||||
import org.egovframe.cloud.reserverequestservice.domain.Reserve;
|
||||
import org.egovframe.cloud.reserverequestservice.domain.ReserveRepositoryCustom;
|
||||
import org.springframework.data.r2dbc.repository.R2dbcRepository;
|
||||
|
||||
/**
|
||||
* org.egovframe.cloud.reserverequestservice.domain.Reserve
|
||||
*
|
||||
* 예약 도메인 repository interface
|
||||
*
|
||||
* @author 표준프레임워크센터 shinmj
|
||||
* @version 1.0
|
||||
* @since 2021/09/15
|
||||
*
|
||||
* <pre>
|
||||
* << 개정이력(Modification Information) >>
|
||||
*
|
||||
* 수정일 수정자 수정내용
|
||||
* ---------- -------- ---------------------------
|
||||
* 2021/09/15 shinmj 최초 생성
|
||||
* </pre>
|
||||
*/
|
||||
public interface ReserveRepository extends R2dbcRepository<Reserve, String>, ReserveRepositoryCustom {
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package org.egovframe.cloud.reserverequestservice.domain;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
/**
|
||||
* org.egovframe.cloud.reserverequestservice.domain.ReserveRepositoryCustom
|
||||
*
|
||||
* 예약 도메인 repository custom interface
|
||||
*
|
||||
* @author 표준프레임워크센터 shinmj
|
||||
* @version 1.0
|
||||
* @since 2021/09/27
|
||||
*
|
||||
* <pre>
|
||||
* << 개정이력(Modification Information) >>
|
||||
*
|
||||
* 수정일 수정자 수정내용
|
||||
* ---------- -------- ---------------------------
|
||||
* 2021/09/27 shinmj 최초 생성
|
||||
* </pre>
|
||||
*/
|
||||
public interface ReserveRepositoryCustom {
|
||||
Mono<Reserve> insert(Reserve reserve);
|
||||
Flux<Reserve> findAllByReserveDateWithoutSelf(String reserveId, Long reserveItemId, LocalDateTime startDate, LocalDateTime endDate);
|
||||
Mono<Long> findAllByReserveDateWithoutSelfCount(String reserveId, Long reserveItemId, LocalDateTime startDate, LocalDateTime endDate);
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
package org.egovframe.cloud.reserverequestservice.domain;
|
||||
|
||||
import static org.springframework.data.relational.core.query.Criteria.*;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.data.r2dbc.core.R2dbcEntityTemplate;
|
||||
import org.springframework.data.relational.core.query.Query;
|
||||
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
/**
|
||||
* org.egovframe.cloud.reserverequestservice.domain.ReserveRepositoryImpl
|
||||
*
|
||||
* 예약 도메인 repository custom interface 구현체
|
||||
*
|
||||
* @author 표준프레임워크센터 shinmj
|
||||
* @version 1.0
|
||||
* @since 2021/09/27
|
||||
*
|
||||
* <pre>
|
||||
* << 개정이력(Modification Information) >>
|
||||
*
|
||||
* 수정일 수정자 수정내용
|
||||
* ---------- -------- ---------------------------
|
||||
* 2021/09/27 shinmj 최초 생성
|
||||
* </pre>
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
public class ReserveRepositoryImpl implements ReserveRepositoryCustom {
|
||||
|
||||
private final R2dbcEntityTemplate entityTemplate;
|
||||
|
||||
/**
|
||||
* 예약 insert
|
||||
* pk(reserveId)를 서비스에서 생성하여 insert 하기 위함.
|
||||
*
|
||||
* @param reserve
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public Mono<Reserve> insert(Reserve reserve) {
|
||||
return entityTemplate.insert(reserve);
|
||||
}
|
||||
|
||||
/**
|
||||
* 조회 기간에 예약된 건 조회
|
||||
* 현 예약건은 제외
|
||||
*
|
||||
* @param reserveItemId
|
||||
* @param startDate
|
||||
* @param endDate
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public Flux<Reserve> findAllByReserveDateWithoutSelf(String reserveId, Long reserveItemId, LocalDateTime startDate, LocalDateTime endDate) {
|
||||
return entityTemplate.select(Reserve.class)
|
||||
.matching(Query.query(where("reserve_item_id").is(reserveItemId)
|
||||
.and ("reserve_start_date").lessThanOrEquals(endDate)
|
||||
.and("reserve_end_date").greaterThanOrEquals(startDate)
|
||||
.and("reserve_id").not(reserveId)
|
||||
))
|
||||
.all();
|
||||
}
|
||||
|
||||
/**
|
||||
* 조회 기간에 예약된 건수 조회
|
||||
* 현 예약건은 제외
|
||||
*
|
||||
* @param reserveItemId
|
||||
* @param startDate
|
||||
* @param endDate
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public Mono<Long> findAllByReserveDateWithoutSelfCount(String reserveId, Long reserveItemId, LocalDateTime startDate, LocalDateTime endDate) {
|
||||
return entityTemplate.select(Reserve.class)
|
||||
.matching(Query.query(where("reserve_item_id").is(reserveItemId)
|
||||
.and ("reserve_start_date").lessThanOrEquals(endDate)
|
||||
.and("reserve_end_date").greaterThanOrEquals(startDate)
|
||||
.and("reserve_id").not(reserveId)
|
||||
))
|
||||
.count();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package org.egovframe.cloud.reserverequestservice.domain;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
@Getter
|
||||
@RequiredArgsConstructor
|
||||
public enum ReserveStatus {
|
||||
REQUEST("request", "예약 신청"),
|
||||
APPROVE("approve", "예약 승인"),
|
||||
CANCEL("cancel", "예약 취소"),
|
||||
DONE("done", "완료");
|
||||
|
||||
private final String key;
|
||||
private final String title;
|
||||
}
|
||||
@@ -0,0 +1,311 @@
|
||||
package org.egovframe.cloud.reserverequestservice.service;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.egovframe.cloud.common.config.GlobalConstant;
|
||||
import org.egovframe.cloud.common.exception.BusinessMessageException;
|
||||
import org.egovframe.cloud.reactive.service.ReactiveAbstractService;
|
||||
import org.egovframe.cloud.reserverequestservice.api.dto.ReserveResponseDto;
|
||||
import org.egovframe.cloud.reserverequestservice.api.dto.ReserveSaveRequestDto;
|
||||
import org.egovframe.cloud.reserverequestservice.domain.Category;
|
||||
import org.egovframe.cloud.reserverequestservice.domain.Reserve;
|
||||
import org.egovframe.cloud.reserverequestservice.domain.ReserveRepository;
|
||||
import org.egovframe.cloud.reserverequestservice.domain.ReserveStatus;
|
||||
import org.springframework.amqp.core.*;
|
||||
import org.springframework.cloud.stream.function.StreamBridge;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.ReactiveSecurityContextHolder;
|
||||
import org.springframework.security.core.context.SecurityContext;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
import reactor.core.scheduler.Schedulers;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
/**
|
||||
* org.egovframe.cloud.reserverequestservice.service.ReserveService
|
||||
* <p>
|
||||
* 예약 신청 service class
|
||||
*
|
||||
* @author 표준프레임워크센터 shinmj
|
||||
* @version 1.0
|
||||
* @since 2021/09/17
|
||||
*
|
||||
* <pre>
|
||||
* << 개정이력(Modification Information) >>
|
||||
*
|
||||
* 수정일 수정자 수정내용
|
||||
* ---------- -------- ---------------------------
|
||||
* 2021/09/17 shinmj 최초 생성
|
||||
* </pre>
|
||||
*/
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
@Transactional
|
||||
@Service
|
||||
public class ReserveService extends ReactiveAbstractService {
|
||||
private final ReserveRepository reserveRepository;
|
||||
private final StreamBridge streamBridge;
|
||||
private final AmqpAdmin amqpAdmin;
|
||||
|
||||
/**
|
||||
* entity -> dto 변환
|
||||
*
|
||||
* @param reserve
|
||||
* @return
|
||||
*/
|
||||
private Mono<ReserveResponseDto> convertReserveResponseDto(Reserve reserve) {
|
||||
return Mono.just(ReserveResponseDto.builder()
|
||||
.entity(reserve)
|
||||
.build());
|
||||
}
|
||||
|
||||
/**
|
||||
* 현재 로그인 사용자 id
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private Mono<String> getUserId() {
|
||||
return ReactiveSecurityContextHolder.getContext()
|
||||
.map(SecurityContext::getAuthentication)
|
||||
.filter(Authentication::isAuthenticated)
|
||||
.map(Authentication::getPrincipal)
|
||||
.map(String.class::cast);
|
||||
}
|
||||
|
||||
/**
|
||||
* 예약 신청 저장
|
||||
*
|
||||
* @param saveRequestDto
|
||||
* @return
|
||||
*/
|
||||
public Mono<ReserveResponseDto> create(ReserveSaveRequestDto saveRequestDto) {
|
||||
return Mono.just(saveRequestDto)
|
||||
.flatMap(dto -> {
|
||||
String uuid = UUID.randomUUID().toString();
|
||||
dto.setReserveId(uuid);
|
||||
dto.setReserveStatusId(ReserveStatus.REQUEST.getKey());
|
||||
return Mono.just(dto.toEntity());
|
||||
})
|
||||
.zipWith(getUserId())
|
||||
.flatMap(tuple -> {
|
||||
tuple.getT1().setCreatedInfo(LocalDateTime.now(), tuple.getT2());
|
||||
return Mono.just(tuple.getT1());
|
||||
})
|
||||
.flatMap(reserveRepository::insert)
|
||||
.flatMap(this::convertReserveResponseDto);
|
||||
}
|
||||
|
||||
/**
|
||||
* 예약 신청 - 실시간
|
||||
* 예약 정보 저장 후 재고 변경을 위해 이벤트 publish
|
||||
*
|
||||
* @param saveRequestDto
|
||||
* @return
|
||||
*/
|
||||
public Mono<ReserveResponseDto> saveForEvent(ReserveSaveRequestDto saveRequestDto) {
|
||||
return create(saveRequestDto)
|
||||
.flatMap(reserveResponseDto ->
|
||||
Mono.fromCallable(() -> {
|
||||
//예약 저장 후 해당 id로 queue 생성
|
||||
Exchange ex = ExchangeBuilder.directExchange(GlobalConstant.SUCCESS_OR_NOT_EX_NAME)
|
||||
.durable(true).build();
|
||||
amqpAdmin.declareExchange(ex);
|
||||
|
||||
Queue queue = QueueBuilder.durable(reserveResponseDto.getReserveId()).build();
|
||||
amqpAdmin.declareQueue(queue);
|
||||
|
||||
Binding binding = BindingBuilder.bind(queue)
|
||||
.to(ex)
|
||||
.with(reserveResponseDto.getReserveId())
|
||||
.noargs();
|
||||
amqpAdmin.declareBinding(binding);
|
||||
|
||||
log.info("Biding successfully created");
|
||||
|
||||
streamBridge.send("reserveRequest-out-0", reserveResponseDto);
|
||||
|
||||
return reserveResponseDto;
|
||||
}).subscribeOn(Schedulers.boundedElastic())
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 예약 신청 - 실시간
|
||||
* 이벤트 스트림을 타지 않는 경우 (재고 변경 이벤트가 없는 경우: 공간, 장비)
|
||||
*
|
||||
* @param saveRequestDto
|
||||
* @return
|
||||
*/
|
||||
public Mono<ReserveResponseDto> save(ReserveSaveRequestDto saveRequestDto) {
|
||||
return Mono.just(saveRequestDto)
|
||||
.flatMap(this::checkValidation)
|
||||
.onErrorResume(throwable -> Mono.error(throwable))
|
||||
.flatMap(dto -> {
|
||||
String uuid = UUID.randomUUID().toString();
|
||||
dto.setReserveId(uuid);
|
||||
dto.setReserveStatusId(ReserveStatus.APPROVE.getKey());
|
||||
return Mono.just(dto.toEntity());
|
||||
}).zipWith(getUserId())
|
||||
.flatMap(tuple -> Mono.just(tuple.getT1().setCreatedInfo(LocalDateTime.now(), tuple.getT2())))
|
||||
.flatMap(reserveRepository::insert)
|
||||
.flatMap(this::convertReserveResponseDto);
|
||||
}
|
||||
|
||||
private Mono<ReserveSaveRequestDto> checkValidation(ReserveSaveRequestDto saveRequestDto) {
|
||||
if (Category.EQUIPMENT.isEquals(saveRequestDto.getCategoryId())) {
|
||||
return checkEquipment(saveRequestDto);
|
||||
}else if (Category.SPACE.isEquals(saveRequestDto.getCategoryId())) {
|
||||
return checkSpace(saveRequestDto);
|
||||
}
|
||||
return Mono.error(new BusinessMessageException("저장 할 수 없습니다."));
|
||||
}
|
||||
|
||||
/**
|
||||
* 예약 날자 validation
|
||||
*
|
||||
* @param saveRequestDto
|
||||
* @return
|
||||
*/
|
||||
private Mono<ReserveSaveRequestDto> checkReserveDate(ReserveSaveRequestDto saveRequestDto) {
|
||||
LocalDateTime startDate = saveRequestDto.getReserveMeansId().equals("realtime") ?
|
||||
saveRequestDto.getRequestStartDate() : saveRequestDto.getOperationStartDate();
|
||||
LocalDateTime endDate = saveRequestDto.getReserveMeansId().equals("realtime") ?
|
||||
saveRequestDto.getRequestEndDate() : saveRequestDto.getOperationEndDate();
|
||||
|
||||
if (saveRequestDto.getReserveStartDate().isBefore(startDate)) {
|
||||
return Mono.error(new BusinessMessageException("시작일이 운영/예약 시작일 이전입니다."));
|
||||
}
|
||||
|
||||
if (saveRequestDto.getReserveEndDate().isAfter(endDate)) {
|
||||
return Mono.error(new BusinessMessageException("종료일이 운영/예약 종료일 이후입니다."));
|
||||
}
|
||||
if (saveRequestDto.getIsPeriod()) {
|
||||
long between = ChronoUnit.DAYS.between(saveRequestDto.getReserveStartDate(),
|
||||
saveRequestDto.getReserveEndDate());
|
||||
if (saveRequestDto.getPeriodMaxCount() < between) {
|
||||
return Mono.error(new BusinessMessageException("최대 예약 가능 일수보다 예약기간이 깁니다. (최대 예약 가능일 수 : "+saveRequestDto.getPeriodMaxCount()+")"));
|
||||
}
|
||||
}
|
||||
return Mono.just(saveRequestDto);
|
||||
}
|
||||
|
||||
/**
|
||||
* 공간 예약 시 예약 날짜에 다른 예약이 있는지 체크
|
||||
*
|
||||
* @param saveRequestDto
|
||||
* @return
|
||||
*/
|
||||
private Mono<ReserveSaveRequestDto> checkSpace(ReserveSaveRequestDto saveRequestDto) {
|
||||
return this.checkReserveDate(saveRequestDto)
|
||||
.flatMap(result -> reserveRepository.findAllByReserveDateWithoutSelfCount(
|
||||
result.getReserveId(),
|
||||
result.getReserveItemId(),
|
||||
result.getReserveStartDate(),
|
||||
result.getReserveEndDate())
|
||||
.flatMap(count -> {
|
||||
if (count > 0) {
|
||||
return Mono.error(new BusinessMessageException("해당 날짜에는 예약할 수 없습니다."));
|
||||
}
|
||||
return Mono.just(result);
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 장비 예약 시 예약 날짜에 예약 가능한 재고 체크
|
||||
*
|
||||
* @param saveRequestDto
|
||||
* @return
|
||||
*/
|
||||
private Mono<ReserveSaveRequestDto> checkEquipment(ReserveSaveRequestDto saveRequestDto) {
|
||||
return this.checkReserveDate(saveRequestDto)
|
||||
.flatMap(result -> this.getMaxByReserveDateWithoutSelf(
|
||||
result.getReserveId(),
|
||||
result.getReserveItemId(),
|
||||
result.getReserveStartDate(),
|
||||
result.getReserveEndDate())
|
||||
.flatMap(max -> {
|
||||
if ((result.getTotalQty() - max) < result.getReserveQty()) {
|
||||
return Mono.just(false);
|
||||
}
|
||||
return Mono.just(true);
|
||||
})
|
||||
.flatMap(isValid -> {
|
||||
if (!isValid) {
|
||||
return Mono.error(new BusinessMessageException("해당 날짜에 예약할 수 있는 재고수량이 없습니다."));
|
||||
}
|
||||
return Mono.just(saveRequestDto);
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 예약물품에 대해 날짜별 예약된 수량 max 조회
|
||||
* 현 예약 건 제외
|
||||
*
|
||||
* @param reserveItemId
|
||||
* @param startDate
|
||||
* @param endDate
|
||||
* @return
|
||||
*/
|
||||
private Mono<Integer> getMaxByReserveDateWithoutSelf(String reserveId, Long reserveItemId, LocalDateTime startDate, LocalDateTime endDate) {
|
||||
Flux<Reserve> reserveFlux = reserveRepository.findAllByReserveDateWithoutSelf(reserveId, reserveItemId, startDate, endDate)
|
||||
.switchIfEmpty(Flux.empty());
|
||||
|
||||
if (reserveFlux.equals(Flux.empty())) {
|
||||
return Mono.just(0);
|
||||
}
|
||||
|
||||
long between = ChronoUnit.DAYS.between(startDate, endDate);
|
||||
return Flux.fromStream(IntStream.iterate(0, i -> i + 1)
|
||||
.limit(between)
|
||||
.mapToObj(i -> startDate.plusDays(i)))
|
||||
.flatMap(localDateTime ->
|
||||
reserveFlux.map(findReserve -> {
|
||||
if (localDateTime.isAfter(findReserve.getReserveStartDate())
|
||||
|| localDateTime.isBefore(findReserve.getReserveEndDate())) {
|
||||
return findReserve.getReserveQty();
|
||||
}
|
||||
return 0;
|
||||
}).reduce(0, (x1, x2) -> x1 + x2))
|
||||
.groupBy(integer -> integer)
|
||||
.flatMap(group -> group.reduce((x1,x2) -> x1 > x2?x1:x2))
|
||||
.last();
|
||||
}
|
||||
|
||||
/**
|
||||
* 예약 신청 후 예약 물품 재고 변경 성공 시 예약승인으로 상태 변경
|
||||
*
|
||||
* @param reserveId
|
||||
* @param reserveStatus
|
||||
* @return
|
||||
*/
|
||||
public Mono<Void> updateStatus(String reserveId, ReserveStatus reserveStatus) {
|
||||
log.info("update : {} , {}", reserveId, reserveStatus);
|
||||
return reserveRepository.findById(reserveId)
|
||||
.map(reserve -> reserve.updateStatus(reserveStatus.getKey()))
|
||||
.flatMap(reserveRepository::save)
|
||||
.then();
|
||||
}
|
||||
|
||||
/**
|
||||
* 예약 신청 후 예약 물품 재고 변경 실패 시 해당 예약 건 삭제
|
||||
*
|
||||
* @param reserveId
|
||||
* @return
|
||||
*/
|
||||
public Mono<Void> delete(String reserveId) {
|
||||
log.info("delete {}", reserveId);
|
||||
return reserveRepository.findById(reserveId)
|
||||
.flatMap(reserveRepository::delete)
|
||||
.then();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
spring:
|
||||
application:
|
||||
name: reserve-request-service
|
||||
|
||||
server:
|
||||
port: 0
|
||||
|
||||
# config server actuator
|
||||
management:
|
||||
endpoints:
|
||||
web:
|
||||
exposure:
|
||||
include: refresh, health, beans
|
||||
@@ -0,0 +1,5 @@
|
||||
spring:
|
||||
cloud:
|
||||
config:
|
||||
uri: http://localhost:8888
|
||||
name: reserve-request-service
|
||||
@@ -0,0 +1,26 @@
|
||||
-- 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)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
ALTER TABLE reserve COMMENT '예약 신청&확인';
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
package org.egovframe.cloud.reserverequestservice;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
|
||||
@SpringBootTest
|
||||
class ReserveRequestServiceApplicationTests {
|
||||
|
||||
@Test
|
||||
void contextLoads() {
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
spring:
|
||||
application:
|
||||
name: reserve-request-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
|
||||
path: /h2
|
||||
|
||||
logging.level:
|
||||
org.hibernate.SQL: debug
|
||||
|
||||
file:
|
||||
directory: ${user.home}/msa-attach-volume
|
||||
messages:
|
||||
directory: ${file.directory}/messages
|
||||
|
||||
# jwt token
|
||||
token:
|
||||
secret: egovframe_user_token
|
||||
|
||||
# ftp server
|
||||
ftp:
|
||||
enabled: false # ftp 사용 여부, FTP 서버에 최상위 디렉토리 자동 생성 및 구현체를 결정하게 된다.
|
||||
|
||||
# eureka 가 포함되면 eureka server 도 등록되므로 해제한다.
|
||||
eureka:
|
||||
client:
|
||||
register-with-eureka: false
|
||||
fetch-registry: false
|
||||
Reference in New Issue
Block a user