Initial commit
This commit is contained in:
@@ -0,0 +1,36 @@
|
||||
package org.egovframe.cloud.reservechecksevice;
|
||||
|
||||
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 reactivefeign.spring.config.EnableReactiveFeignClients;
|
||||
import reactor.blockhound.BlockHound;
|
||||
|
||||
import java.security.Security;
|
||||
|
||||
@ComponentScan({"org.egovframe.cloud.common", "org.egovframe.cloud.reactive", "org.egovframe.cloud.reservechecksevice"}) // org.egovframe.cloud.common package 포함하기 위해
|
||||
@EnableDiscoveryClient
|
||||
@EnableReactiveFeignClients
|
||||
@SpringBootApplication
|
||||
public class ReserveCheckSeviceApplication {
|
||||
|
||||
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(ReserveCheckSeviceApplication.class, args);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,174 @@
|
||||
package org.egovframe.cloud.reservechecksevice.api.reserve;
|
||||
|
||||
import java.time.LocalDate;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.egovframe.cloud.common.dto.RequestDto;
|
||||
import org.egovframe.cloud.reservechecksevice.api.reserve.dto.*;
|
||||
import org.egovframe.cloud.reservechecksevice.domain.reserve.Category;
|
||||
import org.egovframe.cloud.reservechecksevice.service.reserve.ReserveService;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.ReactiveSecurityContextHolder;
|
||||
import org.springframework.security.core.context.SecurityContext;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import javax.validation.Valid;
|
||||
|
||||
/**
|
||||
* org.egovframe.cloud.reservechecksevice.api.reserve.ReserveApiController
|
||||
* <p>
|
||||
* 예약 확인 rest controller class
|
||||
*
|
||||
* @author 표준프레임워크센터 shinmj
|
||||
* @version 1.0
|
||||
* @since 2021/09/17
|
||||
*
|
||||
* <pre>
|
||||
* << 개정이력(Modification Information) >>
|
||||
*
|
||||
* 수정일 수정자 수정내용
|
||||
* ---------- -------- ---------------------------
|
||||
* 2021/09/17 shinmj 최초 생성
|
||||
* </pre>
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
@RestController
|
||||
public class ReserveApiController {
|
||||
|
||||
private final ReserveService reserveService;
|
||||
|
||||
private final Environment env;
|
||||
|
||||
/**
|
||||
* 서비스 상태 확인
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/actuator/health-info")
|
||||
public String status() {
|
||||
return String.format("GET Reserve Check Service on" +
|
||||
"\n local.server.port :" + env.getProperty("local.server.port")
|
||||
+ "\n egov.message :" + env.getProperty("egov.message")
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 예약 확인(신청) 목록 조회
|
||||
* 관리자인 경우 모두 조회
|
||||
*
|
||||
* @param requestDto
|
||||
* @param page
|
||||
* @param size
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/api/v1/reserves")
|
||||
@ResponseStatus(HttpStatus.OK)
|
||||
public Mono<Page<ReserveListResponseDto>> search(ReserveRequestDto requestDto,
|
||||
@RequestParam(name = "page") int page,
|
||||
@RequestParam(name = "size") int size) {
|
||||
return reserveService.search(requestDto, PageRequest.of(page, size));
|
||||
}
|
||||
|
||||
/**
|
||||
* 사용자별 예약 목록 조회
|
||||
*
|
||||
* @param userId
|
||||
* @param requestDto
|
||||
* @param page
|
||||
* @param size
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/api/v1/{userId}/reserves")
|
||||
@ResponseStatus(HttpStatus.OK)
|
||||
public Mono<Page<ReserveListResponseDto>> searchForUser(@PathVariable String userId,
|
||||
ReserveRequestDto requestDto,
|
||||
@RequestParam(name = "page") int page,
|
||||
@RequestParam(name = "size") int size) {
|
||||
return reserveService.searchForUser(userId, requestDto, PageRequest.of(page, size));
|
||||
}
|
||||
|
||||
/**
|
||||
* 예약 한건 조회
|
||||
*
|
||||
* @param reserveId
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/api/v1/reserves/{reserveId}")
|
||||
@ResponseStatus(HttpStatus.OK)
|
||||
public Mono<ReserveResponseDto> findById(@PathVariable String reserveId) {
|
||||
return reserveService.findReserveById(reserveId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 예약 취소
|
||||
*
|
||||
* @param reserveId
|
||||
* @return
|
||||
*/
|
||||
@PutMapping("/api/v1/reserves/cancel/{reserveId}")
|
||||
@ResponseStatus(HttpStatus.NO_CONTENT)
|
||||
public Mono<Void> cancel(@PathVariable String reserveId, @RequestBody ReserveCancelRequestDto cancelRequestDto) {
|
||||
return reserveService.cancel(reserveId, cancelRequestDto);
|
||||
}
|
||||
|
||||
/**
|
||||
* 예약 승인
|
||||
*
|
||||
* @param reserveId
|
||||
* @return
|
||||
*/
|
||||
@PutMapping("/api/v1/reserves/approve/{reserveId}")
|
||||
@ResponseStatus(HttpStatus.NO_CONTENT)
|
||||
public Mono<Void> approve(@PathVariable String reserveId) {
|
||||
return reserveService.approve(reserveId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 예약 정보 수정
|
||||
*
|
||||
* @param reserveId
|
||||
* @param updateRequestDto
|
||||
* @return
|
||||
*/
|
||||
@PutMapping("/api/v1/reserves/{reserveId}")
|
||||
@ResponseStatus(HttpStatus.NO_CONTENT)
|
||||
public Mono<Void> update(@PathVariable String reserveId, @Valid @RequestBody ReserveUpdateRequestDto updateRequestDto) {
|
||||
return reserveService.update(reserveId, updateRequestDto).then();
|
||||
}
|
||||
|
||||
/**
|
||||
* 관리자 예약 신청
|
||||
* 관리자의 경우 실시간이어도 이벤트 스트림 거치지 않고 바로 예약 처리
|
||||
*
|
||||
* @param saveRequestDto
|
||||
* @return
|
||||
*/
|
||||
@PostMapping("/api/v1/reserves")
|
||||
@ResponseStatus(HttpStatus.CREATED)
|
||||
public Mono<ReserveResponseDto> create(@Valid @RequestBody ReserveSaveRequestDto saveRequestDto) {
|
||||
return reserveService.create(saveRequestDto);
|
||||
}
|
||||
|
||||
/**
|
||||
* 예약물품 별 조회기간 내 예약 목록 조회
|
||||
*
|
||||
* @param reserveItemId
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/api/v1/reserves/{reserveItemId}/inventories")
|
||||
@ResponseStatus(HttpStatus.OK)
|
||||
public Mono<Integer> countInventory(@PathVariable Long reserveItemId,
|
||||
@RequestParam(name = "startDate") @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate startDate,
|
||||
@RequestParam(name = "endDate") @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate endDate) {
|
||||
return reserveService.countInventory(reserveItemId,startDate.atTime(1,1), endDate.atTime(1,1));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package org.egovframe.cloud.reservechecksevice.api.reserve.dto;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.ToString;
|
||||
|
||||
/**
|
||||
* org.egovframe.cloud.reservechecksevice.api.reserve.dto.ReserveCancelRequestDto
|
||||
* <p>
|
||||
* 예약 취소 요청 dto class
|
||||
*
|
||||
* @author 표준프레임워크센터 shinmj
|
||||
* @version 1.0
|
||||
* @since 2021/10/06
|
||||
*
|
||||
* <pre>
|
||||
* << 개정이력(Modification Information) >>
|
||||
*
|
||||
* 수정일 수정자 수정내용
|
||||
* ---------- -------- ---------------------------
|
||||
* 2021/10/06 shinmj 최초 생성
|
||||
* </pre>
|
||||
*/
|
||||
@Getter
|
||||
@NoArgsConstructor
|
||||
@ToString
|
||||
public class ReserveCancelRequestDto {
|
||||
@NotBlank
|
||||
private String reasonCancelContent;
|
||||
|
||||
@Builder
|
||||
public ReserveCancelRequestDto(String reasonCancelContent) {
|
||||
this.reasonCancelContent = reasonCancelContent;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
package org.egovframe.cloud.reservechecksevice.api.reserve.dto;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.ToString;
|
||||
import org.egovframe.cloud.reservechecksevice.domain.reserve.Reserve;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* org.egovframe.cloud.reservechecksevice.api.reserve.dto.ReserveListResponseDto
|
||||
* <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 ReserveListResponseDto {
|
||||
|
||||
private String reserveId;
|
||||
|
||||
private Long locationId;
|
||||
private String categoryId;
|
||||
private Long reserveItemId;
|
||||
private String reserveItemName;
|
||||
private Integer totalQty;
|
||||
private Integer reserveQty;
|
||||
|
||||
private String userId;
|
||||
private String userName;
|
||||
|
||||
private String reserveStatusId;
|
||||
private LocalDateTime createDate;
|
||||
|
||||
@Builder
|
||||
public ReserveListResponseDto(Reserve entity) {
|
||||
this.reserveId = entity.getReserveId();
|
||||
this.locationId = entity.getLocationId();
|
||||
this.categoryId = entity.getCategoryId();
|
||||
this.reserveItemId = entity.getReserveItemId();
|
||||
this.reserveItemName = entity.getReserveItem().getReserveItemName();
|
||||
this.totalQty = entity.getReserveItem().getTotalQty();
|
||||
this.reserveQty = entity.getReserveQty();
|
||||
this.userId = entity.getUserId();
|
||||
this.userName = entity.getUser().getUserName();
|
||||
this.reserveStatusId = entity.getReserveStatusId();
|
||||
this.createDate = entity.getCreateDate();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
package org.egovframe.cloud.reservechecksevice.api.reserve.dto;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.egovframe.cloud.common.dto.RequestDto;
|
||||
|
||||
/**
|
||||
* org.egovframe.cloud.reservechecksevice.api.reserve.dto.ReserveRequestDto
|
||||
* <p>
|
||||
* 얘약 목록 요청 dto class
|
||||
*
|
||||
* @author 표준프레임워크센터 shinmj
|
||||
* @version 1.0
|
||||
* @since 2021/09/27
|
||||
*
|
||||
* <pre>
|
||||
* << 개정이력(Modification Information) >>
|
||||
*
|
||||
* 수정일 수정자 수정내용
|
||||
* ---------- -------- ---------------------------
|
||||
* 2021/09/27 shinmj 최초 생성
|
||||
* </pre>
|
||||
*/
|
||||
@NoArgsConstructor
|
||||
@Getter
|
||||
public class ReserveRequestDto extends RequestDto {
|
||||
private Long locationId;
|
||||
private String categoryId;
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
package org.egovframe.cloud.reservechecksevice.api.reserve.dto;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.ToString;
|
||||
import org.egovframe.cloud.reservechecksevice.client.dto.ReserveItemRelationResponseDto;
|
||||
import org.egovframe.cloud.reservechecksevice.domain.reserve.Reserve;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* org.egovframe.cloud.reservechecksevice.api.reserve.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 ReserveItemRelationResponseDto reserveItem;
|
||||
|
||||
private Integer reserveQty;
|
||||
private LocalDateTime reserveStartDate;
|
||||
private LocalDateTime reserveEndDate;
|
||||
private String reservePurposeContent;
|
||||
private String attachmentCode;
|
||||
|
||||
private String reserveStatusId;
|
||||
|
||||
private String userId;
|
||||
private String userName;
|
||||
private String userContactNo;
|
||||
private String userEmail;
|
||||
|
||||
@Builder
|
||||
public ReserveResponseDto(Reserve entity) {
|
||||
this.reserveId = entity.getReserveId();
|
||||
this.reserveItemId = entity.getReserveItemId();
|
||||
this.reserveItem = ReserveItemRelationResponseDto.builder().entity(entity.getReserveItem()).build();
|
||||
this.reserveQty = entity.getReserveQty();
|
||||
this.reserveStartDate = entity.getReserveStartDate();
|
||||
this.reserveEndDate = entity.getReserveEndDate();
|
||||
this.reservePurposeContent = entity.getReservePurposeContent();
|
||||
this.attachmentCode = entity.getAttachmentCode();
|
||||
this.reserveStatusId = entity.getReserveStatusId();
|
||||
this.userId = entity.getUserId();
|
||||
this.userName = entity.getUser().getUserName();
|
||||
this.userContactNo = entity.getUserContactNo();
|
||||
this.userEmail = entity.getUserEmail();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
package org.egovframe.cloud.reservechecksevice.api.reserve.dto;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import lombok.ToString;
|
||||
import lombok.With;
|
||||
|
||||
import org.egovframe.cloud.reservechecksevice.domain.reserve.Reserve;
|
||||
import org.egovframe.cloud.reservechecksevice.validator.annotation.ReserveSaveValid;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* org.egovframe.cloud.reservechecksevice.api.reserve.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
|
||||
@ReserveSaveValid
|
||||
public class ReserveSaveRequestDto {
|
||||
|
||||
@Setter
|
||||
private String reserveId;
|
||||
|
||||
@NotNull
|
||||
private Long reserveItemId;
|
||||
private Long locationId;
|
||||
private String categoryId;
|
||||
private Integer reserveQty; //예약 신청 인원/수량
|
||||
|
||||
@NotNull
|
||||
private String reservePurposeContent; //예약 목적
|
||||
private String attachmentCode; //첨부파일 코드
|
||||
private LocalDateTime reserveStartDate; //예약 신청 시작일
|
||||
private LocalDateTime reserveEndDate; //예약 신청 종료일
|
||||
private String reserveStatusId; //예약상태 - 공통코드(reserve-status)
|
||||
|
||||
@NotNull
|
||||
private String userId; //예약자
|
||||
|
||||
@NotNull
|
||||
private String userContactNo; //예약자 연락처
|
||||
|
||||
@NotNull
|
||||
private String userEmail; //예약자 이메일
|
||||
|
||||
@Builder
|
||||
public ReserveSaveRequestDto(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.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;
|
||||
}
|
||||
|
||||
public Reserve toEntity() {
|
||||
Reserve reserve = Reserve.builder()
|
||||
.reserveId(this.reserveId)
|
||||
.reserveItemId(this.reserveItemId)
|
||||
.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();
|
||||
reserve.setLocationId(this.locationId);
|
||||
reserve.setCategoryId(this.categoryId);
|
||||
|
||||
return reserve;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
package org.egovframe.cloud.reservechecksevice.api.reserve.dto;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.ToString;
|
||||
import org.egovframe.cloud.reservechecksevice.validator.annotation.ReserveSaveValid;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* org.egovframe.cloud.reservechecksevice.api.reserve.dto.ReserveUpdateRequestDto
|
||||
* <p>
|
||||
* 예약 신청 정보 수정 요청 dto class
|
||||
*
|
||||
* @author 표준프레임워크센터 shinmj
|
||||
* @version 1.0
|
||||
* @since 2021/09/17
|
||||
*
|
||||
* <pre>
|
||||
* << 개정이력(Modification Information) >>
|
||||
*
|
||||
* 수정일 수정자 수정내용
|
||||
* ---------- -------- ---------------------------
|
||||
* 2021/09/17 shinmj 최초 생성
|
||||
* </pre>
|
||||
*/
|
||||
@Getter
|
||||
@NoArgsConstructor
|
||||
@ToString
|
||||
@ReserveSaveValid
|
||||
public class ReserveUpdateRequestDto {
|
||||
|
||||
@NotNull
|
||||
private Long reserveItemId;
|
||||
private String categoryId;
|
||||
private Integer reserveQty; //예약 신청 인원/수량
|
||||
|
||||
@NotNull
|
||||
private String reservePurposeContent; //예약 목적
|
||||
private String attachmentCode; //첨부파일 코드
|
||||
private LocalDateTime reserveStartDate; //예약 신청 시작일
|
||||
private LocalDateTime reserveEndDate; //예약 신청 종료일
|
||||
|
||||
@NotNull
|
||||
private String userId; //예약자
|
||||
|
||||
@NotNull
|
||||
private String userContactNo; //예약자 연락처
|
||||
|
||||
@NotNull
|
||||
private String userEmail; //예약자 이메일
|
||||
|
||||
@Builder
|
||||
public ReserveUpdateRequestDto(Long reserveItemId, String categoryId, Integer reserveQty, String reservePurposeContent, String attachmentCode, LocalDateTime reserveStartDate, LocalDateTime reserveEndDate, String userId, String userContactNo, String userEmail) {
|
||||
this.reserveItemId = reserveItemId;
|
||||
this.categoryId = categoryId;
|
||||
this.reserveQty = reserveQty;
|
||||
this.reservePurposeContent = reservePurposeContent;
|
||||
this.attachmentCode = attachmentCode;
|
||||
this.reserveStartDate = reserveStartDate;
|
||||
this.reserveEndDate = reserveEndDate;
|
||||
this.userId = userId;
|
||||
this.userContactNo = userContactNo;
|
||||
this.userEmail = userEmail;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
package org.egovframe.cloud.reservechecksevice.client;
|
||||
|
||||
import org.egovframe.cloud.reservechecksevice.client.dto.ReserveItemRelationResponseDto;
|
||||
import org.egovframe.cloud.reservechecksevice.client.dto.ReserveItemResponseDto;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PutMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
|
||||
import reactivefeign.spring.config.ReactiveFeignClient;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
/**
|
||||
* org.egovframe.cloud.reservechecksevice.client.ReserveItemServiceClient
|
||||
* <p>
|
||||
* 예약 물품 서비스와 통신하는 feign client interface
|
||||
*
|
||||
* @author 표준프레임워크센터 shinmj
|
||||
* @version 1.0
|
||||
* @since 2021/09/23
|
||||
*
|
||||
* <pre>
|
||||
* << 개정이력(Modification Information) >>
|
||||
*
|
||||
* 수정일 수정자 수정내용
|
||||
* ---------- -------- ---------------------------
|
||||
* 2021/09/23 shinmj 최초 생성
|
||||
* </pre>
|
||||
*/
|
||||
@ReactiveFeignClient(value = "reserve-item-service")
|
||||
public interface ReserveItemServiceClient {
|
||||
/**
|
||||
* 예약 물품 한건 조회
|
||||
*
|
||||
* @param reserveItemId
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/api/v1/reserve-items/{reserveItemId}")
|
||||
Mono<ReserveItemResponseDto> findById(@PathVariable("reserveItemId") Long reserveItemId);
|
||||
|
||||
/**
|
||||
* 예약 물품 한건 조회 시 연결된 공통코드, 지역 정보 조회
|
||||
*
|
||||
* @param reserveItemId
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/api/v1/reserve-items/relations/{reserveItemId}")
|
||||
Mono<ReserveItemRelationResponseDto> findByIdWithRelations(@PathVariable("reserveItemId") Long reserveItemId);
|
||||
|
||||
/**
|
||||
* 관리자가 예약 신청 시 이벤트 스트림 없이 바로 재고 변경
|
||||
*
|
||||
* @param reserveItemId
|
||||
* @param reserveQty
|
||||
* @return
|
||||
*/
|
||||
@PutMapping("/api/v1/reserve-items/{reserveItemId}/inventories")
|
||||
Mono<Boolean> updateInventory(@PathVariable("reserveItemId") Long reserveItemId, @RequestBody Integer reserveQty);
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package org.egovframe.cloud.reservechecksevice.client;
|
||||
|
||||
import org.egovframe.cloud.reservechecksevice.client.dto.UserResponseDto;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
|
||||
import reactivefeign.spring.config.ReactiveFeignClient;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
/**
|
||||
* org.egovframe.cloud.reservechecksevice.client.UserServiceClient
|
||||
* <p>
|
||||
* 사용자 서비스와 통신하는 feign client interface
|
||||
*
|
||||
* @author 표준프레임워크센터 shinmj
|
||||
* @version 1.0
|
||||
* @since 2021/09/30
|
||||
*
|
||||
* <pre>
|
||||
* << 개정이력(Modification Information) >>
|
||||
*
|
||||
* 수정일 수정자 수정내용
|
||||
* ---------- -------- ---------------------------
|
||||
* 2021/09/30 shinmj 최초 생성
|
||||
* </pre>
|
||||
*/
|
||||
@ReactiveFeignClient(value = "user-service")
|
||||
public interface UserServiceClient {
|
||||
|
||||
|
||||
/**
|
||||
* 사용자 단 건 조회
|
||||
*
|
||||
* @param userId
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/api/v1/users/{userId}")
|
||||
Mono<UserResponseDto> findByUserId(@PathVariable("userId") String userId);
|
||||
}
|
||||
@@ -0,0 +1,147 @@
|
||||
package org.egovframe.cloud.reservechecksevice.client.dto;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.ToString;
|
||||
|
||||
import org.egovframe.cloud.reservechecksevice.domain.location.Location;
|
||||
import org.egovframe.cloud.reservechecksevice.domain.reserve.ReserveItem;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* org.egovframe.cloud.reservechecksevice.client.dto.ReserveItemRelationResponseDto
|
||||
* <p>
|
||||
* 얘약 물품 feign client 응답 dto class
|
||||
*
|
||||
* @author 표준프레임워크센터 shinmj
|
||||
* @version 1.0
|
||||
* @since 2021/09/27
|
||||
*
|
||||
* <pre>
|
||||
* << 개정이력(Modification Information) >>
|
||||
*
|
||||
* 수정일 수정자 수정내용
|
||||
* ---------- -------- ---------------------------
|
||||
* 2021/09/27 shinmj 최초 생성
|
||||
* </pre>
|
||||
*/
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Getter
|
||||
@ToString
|
||||
public class ReserveItemRelationResponseDto {
|
||||
private Long reserveItemId; // 예약 물품 id
|
||||
private String reserveItemName; //예약 물품 명
|
||||
private Long locationId;
|
||||
private Location location;
|
||||
private String categoryId; //예약유형 - 공통코드 reserve-category
|
||||
private String categoryName;
|
||||
private Integer totalQty; //총 재고/수용인원 수
|
||||
private Integer inventoryQty; // 재고/수용인원 수
|
||||
private LocalDateTime operationStartDate; //운영 시작 일
|
||||
private LocalDateTime operationEndDate; //운영 종료 일
|
||||
private String reserveMethodId; // 예약 방법 - 공통코드 reserve-method
|
||||
private String reserveMethodName;
|
||||
private String reserveMeansId; // 예약 구분 (인터넷 예약 시) - 공통코드 reserve-means
|
||||
private String reserveMeansName;
|
||||
private LocalDateTime requestStartDate; //예약 신청 시작 일시
|
||||
private LocalDateTime requestEndDate; //예약 신청 종료 일시
|
||||
private Boolean isPeriod; //기간 지정 가능 여부 - true: 지정 가능, false: 지정 불가
|
||||
private Integer periodMaxCount; // 최대 예약 가능 일 수
|
||||
private String externalUrl; //외부링크
|
||||
private String selectionMeansId; //선별 방법 - 공통코드 reserve-selection
|
||||
private String selectionMeansName;
|
||||
private Boolean isPaid; // 유/무료 - false: 무료, true: 유료
|
||||
private BigDecimal usageCost; //이용 요금
|
||||
private Boolean isUse; //사용여부
|
||||
private String purpose; //용도
|
||||
private String address; //주소
|
||||
private String targetId; //이용 대상 - 공통코드 reserve-target
|
||||
private String targetName;
|
||||
private String excluded; // 사용허가 제외대상
|
||||
private String homepage; //홈페이지 주소
|
||||
private String contact; //문의처
|
||||
private String managerDept; //담당자 소속
|
||||
private String managerName; //담당자 이름
|
||||
private String managerContact; //담당자 연락처
|
||||
|
||||
@Builder
|
||||
public ReserveItemRelationResponseDto(ReserveItem entity) {
|
||||
this.reserveItemId = entity.getReserveItemId();
|
||||
this.reserveItemName = entity.getReserveItemName();
|
||||
this.locationId = entity.getLocationId();
|
||||
this.location = entity.getLocation();
|
||||
this.categoryId = entity.getCategoryId();
|
||||
this.categoryName = entity.getCategoryName();
|
||||
this.totalQty = entity.getTotalQty();
|
||||
this.inventoryQty = entity.getInventoryQty();
|
||||
this.operationStartDate = entity.getOperationStartDate();
|
||||
this.operationEndDate = entity.getOperationEndDate();
|
||||
this.reserveMethodId = entity.getReserveMethodId();
|
||||
this.reserveMethodName = entity.getReserveMethodName();
|
||||
this.reserveMeansId = entity.getReserveMeansId();
|
||||
this.reserveMeansName = entity.getReserveMeansName();
|
||||
this.requestStartDate = entity.getRequestStartDate();
|
||||
this.requestEndDate = entity.getRequestEndDate();
|
||||
this.isPeriod = entity.getIsPeriod();
|
||||
this.periodMaxCount = entity.getPeriodMaxCount();
|
||||
this.externalUrl = entity.getExternalUrl();
|
||||
this.selectionMeansId = entity.getSelectionMeansId();
|
||||
this.selectionMeansName = entity.getSelectionMeansName();
|
||||
this.isPaid = entity.getIsPaid();
|
||||
this.usageCost = entity.getUsageCost();
|
||||
this.isUse = entity.getIsUse();
|
||||
this.purpose = entity.getPurpose();
|
||||
this.address = entity.getAddress();
|
||||
this.targetId = entity.getTargetId();
|
||||
this.targetName = entity.getTargetName();
|
||||
this.excluded = entity.getExcluded();
|
||||
this.homepage = entity.getHomepage();
|
||||
this.contact = entity.getContact();
|
||||
this.managerDept = entity.getManagerDept();
|
||||
this.managerName = entity.getManagerName();
|
||||
this.managerContact = entity.getManagerContact();
|
||||
}
|
||||
|
||||
public ReserveItem toEntity() {
|
||||
return ReserveItem.builder()
|
||||
.reserveItemName(this.reserveItemName)
|
||||
.locationId(this.locationId)
|
||||
.location(this.location)
|
||||
.categoryId(this.categoryId)
|
||||
.categoryName(this.categoryName)
|
||||
.totalQty(this.totalQty)
|
||||
.inventoryQty(this.inventoryQty)
|
||||
.operationStartDate(this.operationStartDate)
|
||||
.operationEndDate(this.operationEndDate)
|
||||
.reserveMethodId(this.reserveMethodId)
|
||||
.reserveMethodName(this.reserveMethodName)
|
||||
.reserveMeansId(this.reserveMeansId)
|
||||
.reserveMeansName(this.reserveMeansName)
|
||||
.requestStartDate(this.requestStartDate)
|
||||
.requestEndDate(this.requestEndDate)
|
||||
.isPeriod(this.isPeriod)
|
||||
.periodMaxCount(this.periodMaxCount)
|
||||
.externalUrl(this.externalUrl)
|
||||
.selectionMeansId(this.selectionMeansId)
|
||||
.selectionMeansName(this.selectionMeansName)
|
||||
.isPaid(this.isPaid)
|
||||
.usageCost(this.usageCost)
|
||||
.isUse(this.isUse)
|
||||
.purpose(this.purpose)
|
||||
.address(this.address)
|
||||
.targetId(this.targetId)
|
||||
.targetName(this.targetName)
|
||||
.excluded(this.excluded)
|
||||
.homepage(this.homepage)
|
||||
.contact(this.contact)
|
||||
.managerDept(this.managerDept)
|
||||
.managerName(this.managerName)
|
||||
.managerContact(this.managerContact)
|
||||
.build();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
package org.egovframe.cloud.reservechecksevice.client.dto;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.ToString;
|
||||
import org.egovframe.cloud.reservechecksevice.domain.reserve.ReserveItem;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* org.egovframe.cloud.reserveitemservice.api.reserveItem.dto.ReserveItemResponseDto
|
||||
* <p>
|
||||
* 예약 물품 응답 dto class
|
||||
*
|
||||
* @author 표준프레임워크센터 shinmj
|
||||
* @version 1.0
|
||||
* @since 2021/09/13
|
||||
*
|
||||
* <pre>
|
||||
* << 개정이력(Modification Information) >>
|
||||
*
|
||||
* 수정일 수정자 수정내용
|
||||
* ---------- -------- ---------------------------
|
||||
* 2021/09/13 shinmj 최초 생성
|
||||
* </pre>
|
||||
*/
|
||||
@Getter
|
||||
@NoArgsConstructor
|
||||
@ToString
|
||||
public class ReserveItemResponseDto {
|
||||
private Long reserveItemId; // 예약 물품 id
|
||||
private String reserveItemName; //예약 물품 명
|
||||
private Long locationId;
|
||||
private String categoryId; //예약유형 - 공통코드 reserve-category
|
||||
private Integer totalQty; //총 재고/수용인원 수
|
||||
private Integer inventoryQty; // 재고/수용인원 수
|
||||
private LocalDateTime operationStartDate; //운영 시작 일
|
||||
private LocalDateTime operationEndDate; //운영 종료 일
|
||||
private String reserveMethodId; // 예약 방법 - 공통코드 reserve-method
|
||||
private String reserveMeansId; // 예약 구분 (인터넷 예약 시) - 공통코드 reserve-means
|
||||
private LocalDateTime requestStartDate; //예약 신청 시작 일시
|
||||
private LocalDateTime requestEndDate; //예약 신청 종료 일시
|
||||
private Boolean isPeriod; //기간 지정 가능 여부 - true: 지정 가능, false: 지정 불가
|
||||
private Integer periodMaxCount; // 최대 예약 가능 일 수
|
||||
private String externalUrl; //외부링크
|
||||
private String selectionMeansId; //선별 방법 - 공통코드 reserve-selection
|
||||
private Boolean isPaid; // 유/무료 - true: 무료, false: 유료
|
||||
private BigDecimal usageCost; //이용 요금
|
||||
private Boolean isUse; //사용여부
|
||||
private String purpose; //용도
|
||||
private String address; //주소
|
||||
private String targetId; //이용 대상 - 공통코드 reserve-target
|
||||
private String excluded; // 사용허가 제외대상
|
||||
private String homepage; //홈페이지 주소
|
||||
private String contact; //문의처
|
||||
private String managerDept; //담당자 소속
|
||||
private String managerName; //담당자 이름
|
||||
private String managerContact; //담당자 연락처
|
||||
|
||||
@Builder
|
||||
public ReserveItemResponseDto(ReserveItem reserveItem) {
|
||||
this.reserveItemId = reserveItem.getReserveItemId();
|
||||
this.reserveItemName = reserveItem.getReserveItemName();
|
||||
this.locationId = reserveItem.getLocationId();
|
||||
this.categoryId = reserveItem.getCategoryId();
|
||||
this.totalQty = reserveItem.getTotalQty();
|
||||
this.inventoryQty = reserveItem.getInventoryQty();
|
||||
this.operationStartDate = reserveItem.getOperationStartDate();
|
||||
this.operationEndDate = reserveItem.getOperationEndDate();
|
||||
this.reserveMethodId = reserveItem.getReserveMethodId();
|
||||
this.reserveMeansId = reserveItem.getReserveMeansId();
|
||||
this.requestStartDate = reserveItem.getRequestStartDate();
|
||||
this.requestEndDate = reserveItem.getRequestEndDate();
|
||||
this.isPeriod = reserveItem.getIsPeriod();
|
||||
this.periodMaxCount = reserveItem.getPeriodMaxCount();
|
||||
this.externalUrl = reserveItem.getExternalUrl();
|
||||
this.selectionMeansId = reserveItem.getSelectionMeansId();
|
||||
this.isPaid = reserveItem.getIsPaid();
|
||||
this.usageCost = reserveItem.getUsageCost();
|
||||
this.isUse = reserveItem.getIsUse();
|
||||
this.purpose = reserveItem.getPurpose();
|
||||
this.address = reserveItem.getAddress();
|
||||
this.targetId = reserveItem.getTargetId();
|
||||
this.excluded = reserveItem.getExcluded();
|
||||
this.homepage = reserveItem.getHomepage();
|
||||
this.contact = reserveItem.getContact();
|
||||
this.managerDept = reserveItem.getManagerDept();
|
||||
this.managerName = reserveItem.getManagerName();
|
||||
this.managerContact = reserveItem.getManagerContact();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package org.egovframe.cloud.reservechecksevice.client.dto;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* org.egovframe.cloud.userservice.api.user.dto.UserResponseDto
|
||||
* <p>
|
||||
* 사용자 정보 요청시 사용되는 필요한 정보만 담긴 DTO
|
||||
*
|
||||
* @author 표준프레임워크센터 jaeyeolkim
|
||||
* @version 1.0
|
||||
* @since 2021/06/30
|
||||
*
|
||||
* <pre>
|
||||
* << 개정이력(Modification Information) >>
|
||||
*
|
||||
* 수정일 수정자 수정내용
|
||||
* ---------- -------- ---------------------------
|
||||
* 2021/06/30 jaeyeolkim 최초 생성
|
||||
* </pre>
|
||||
*/
|
||||
@Getter
|
||||
public class UserResponseDto {
|
||||
|
||||
private String userId;
|
||||
private String userName;
|
||||
private String email;
|
||||
private String roleId;
|
||||
private String userStateCode;
|
||||
private String googleId;
|
||||
private String kakaoId;
|
||||
private String naverId;
|
||||
private Boolean isSocialUser;
|
||||
private Boolean hasPassword;
|
||||
|
||||
@Builder
|
||||
public UserResponseDto(String userId, String userName, String email, String roleId, String userStateCode, String googleId, String kakaoId, String naverId, Boolean isSocialUser, Boolean hasPassword) {
|
||||
this.userId = userId;
|
||||
this.userName = userName;
|
||||
this.email = email;
|
||||
this.roleId = roleId;
|
||||
this.userStateCode = userStateCode;
|
||||
this.googleId = googleId;
|
||||
this.kakaoId = kakaoId;
|
||||
this.naverId = naverId;
|
||||
this.isSocialUser = isSocialUser;
|
||||
this.hasPassword = hasPassword;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package org.egovframe.cloud.reservechecksevice.config;
|
||||
|
||||
import java.time.Duration;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import io.github.resilience4j.circuitbreaker.CircuitBreakerConfig;
|
||||
import io.github.resilience4j.circuitbreaker.CircuitBreakerRegistry;
|
||||
|
||||
/**
|
||||
* org.egovframe.cloud.portalservice.config.Resilience4JConfig
|
||||
* <p>
|
||||
* Resilience4J Configuration
|
||||
* 기본 설정값으로 운영되어도 무방하다. 이 클래스는 필수는 아니다.
|
||||
* retry 기본값은 최대 3회이고, fallback 이 없는 경우에만 동작하므로 설정하지 않았다.
|
||||
*
|
||||
* @author 표준프레임워크센터 jaeyeolkim
|
||||
* @version 1.0
|
||||
* @since 2021/08/31
|
||||
*
|
||||
* <pre>
|
||||
* << 개정이력(Modification Information) >>
|
||||
*
|
||||
* 수정일 수정자 수정내용
|
||||
* ---------- -------- ---------------------------
|
||||
* 2021/08/31 jaeyeolkim 최초 생성
|
||||
* 2021/10/05 shinmj reactive로 변경
|
||||
* </pre>
|
||||
*/
|
||||
@Configuration
|
||||
public class Resilience4JConfig {
|
||||
|
||||
@Bean
|
||||
public CircuitBreakerRegistry circuitBreakerRegistry() {
|
||||
CircuitBreakerConfig circuitBreakerConfig = CircuitBreakerConfig.custom()
|
||||
.failureRateThreshold(50) // Circuit 열지 말지 결정하는 실패 threshold 퍼센테이지
|
||||
.waitDurationInOpenState(Duration.ofSeconds(5)) // (half closed 전에) circuitBreaker가 open 되기 전에 기다리는 기간
|
||||
.slidingWindowType(CircuitBreakerConfig.SlidingWindowType.COUNT_BASED) // circuit breaker count 기반 처리
|
||||
.slidingWindowSize(10) // 통계 대상 건수 -> N건의 요청중..
|
||||
.build();
|
||||
return CircuitBreakerRegistry.of(circuitBreakerConfig);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
package org.egovframe.cloud.reservechecksevice.domain.location;
|
||||
|
||||
import lombok.*;
|
||||
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 javax.validation.constraints.Size;
|
||||
|
||||
/**
|
||||
* org.egovframe.cloud.reserveitemservice.domain.location.Location
|
||||
*
|
||||
* 예약 지역 도메인 클래스
|
||||
*
|
||||
* @author 표준프레임워크센터 shinmj
|
||||
* @version 1.0
|
||||
* @since 2021/09/06
|
||||
*
|
||||
* <pre>
|
||||
* << 개정이력(Modification Information) >>
|
||||
*
|
||||
* 수정일 수정자 수정내용
|
||||
* ---------- -------- ---------------------------
|
||||
* 2021/09/06 shinmj 최초 생성
|
||||
* </pre>
|
||||
*/
|
||||
@Getter
|
||||
@NoArgsConstructor
|
||||
@ToString
|
||||
public class Location extends BaseEntity {
|
||||
|
||||
@Id
|
||||
private Long locationId;
|
||||
|
||||
@Size(max = 200)
|
||||
@Column
|
||||
private String locationName;
|
||||
@Column
|
||||
private Integer sortSeq;
|
||||
|
||||
@Column("use_at")
|
||||
private Boolean isUse;
|
||||
|
||||
@Builder
|
||||
public Location(Long locationId, String locationName, Integer sortSeq, Boolean isUse) {
|
||||
this.locationId = locationId;
|
||||
this.locationName = locationName;
|
||||
this.sortSeq = sortSeq;
|
||||
this.isUse = isUse;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package org.egovframe.cloud.reservechecksevice.domain.reserve;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
/**
|
||||
* org.egovframe.cloud.reservechecksevice.domain.reserve.Category
|
||||
*
|
||||
* 예약 유형 enum class
|
||||
*
|
||||
* @author 표준프레임워크센터 shinmj
|
||||
* @version 1.0
|
||||
* @since 2021/09/15
|
||||
*
|
||||
* <pre>
|
||||
* << 개정이력(Modification Information) >>
|
||||
*
|
||||
* 수정일 수정자 수정내용
|
||||
* ---------- -------- ---------------------------
|
||||
* 2021/09/15 shinmj 최초 생성
|
||||
* </pre>
|
||||
*/
|
||||
@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,203 @@
|
||||
package org.egovframe.cloud.reservechecksevice.domain.reserve;
|
||||
|
||||
import lombok.*;
|
||||
import org.egovframe.cloud.reactive.domain.BaseEntity;
|
||||
import org.egovframe.cloud.reservechecksevice.api.reserve.dto.ReserveUpdateRequestDto;
|
||||
import org.egovframe.cloud.reservechecksevice.client.dto.UserResponseDto;
|
||||
import org.egovframe.cloud.reservechecksevice.domain.location.Location;
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.annotation.Transient;
|
||||
import org.springframework.data.relational.core.mapping.Column;
|
||||
import org.springframework.data.relational.core.mapping.Table;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
import javax.validation.constraints.Size;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* org.egovframe.cloud.reservechecksevice.domain.reserve.Reserve
|
||||
*
|
||||
* 예약 도메인 클래스
|
||||
*
|
||||
* @author 표준프레임워크센터 shinmj
|
||||
* @version 1.0
|
||||
* @since 2021/09/15
|
||||
*
|
||||
* <pre>
|
||||
* << 개정이력(Modification Information) >>
|
||||
*
|
||||
* 수정일 수정자 수정내용
|
||||
* ---------- -------- ---------------------------
|
||||
* 2021/09/15 shinmj 최초 생성
|
||||
* </pre>
|
||||
*/
|
||||
@Getter
|
||||
@NoArgsConstructor
|
||||
@ToString
|
||||
@With
|
||||
@Table("reserve")
|
||||
public class Reserve extends BaseEntity {
|
||||
|
||||
@Id
|
||||
@Column
|
||||
private String reserveId; //예약 id
|
||||
|
||||
@Column
|
||||
private Long reserveItemId; //예약 물품 id
|
||||
|
||||
@Transient
|
||||
private ReserveItem reserveItem;
|
||||
|
||||
@Setter
|
||||
@Column
|
||||
private Long locationId; //지역 id
|
||||
|
||||
@Setter
|
||||
@Column
|
||||
private String categoryId; //예약유형 - 공통코드 reserve-category
|
||||
|
||||
@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 reasonCancelContent; //예약 취소 사유
|
||||
|
||||
@Column
|
||||
private String userId; //예약자
|
||||
|
||||
@Transient
|
||||
private UserResponseDto user;
|
||||
|
||||
@Column
|
||||
private String userContactNo; //예약자 연락처
|
||||
|
||||
@Column("user_email_addr")
|
||||
private String userEmail; //예약자 이메일
|
||||
|
||||
@Builder
|
||||
public Reserve(String reserveId, Long reserveItemId,
|
||||
ReserveItem reserveItem, Long locationId, String categoryId, Integer reserveQty,
|
||||
String reservePurposeContent, String attachmentCode, LocalDateTime reserveStartDate,
|
||||
LocalDateTime reserveEndDate, String reserveStatusId, String reasonCancelContent, String userId,
|
||||
UserResponseDto user, String userContactNo, String userEmail) {
|
||||
this.reserveId = reserveId;
|
||||
this.reserveItemId = reserveItemId;
|
||||
this.reserveItem = reserveItem;
|
||||
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.reasonCancelContent = reasonCancelContent;
|
||||
this.userId = userId;
|
||||
this.user = user;
|
||||
this.userContactNo = userContactNo;
|
||||
this.userEmail = userEmail;
|
||||
}
|
||||
|
||||
/**
|
||||
* 물품 정보 세팅
|
||||
*
|
||||
* @param reserveItem
|
||||
* @return
|
||||
*/
|
||||
public Reserve setReserveItem(ReserveItem reserveItem) {
|
||||
this.reserveItem = reserveItem;
|
||||
this.reserveItemId = reserveItem.getReserveItemId();
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 예약자 정보 세팅
|
||||
*
|
||||
* @param user
|
||||
* @return
|
||||
*/
|
||||
public Reserve setUser(UserResponseDto user) {
|
||||
this.user = user;
|
||||
this.userId = user.getUserId();
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 예약 상태 업데이트
|
||||
*
|
||||
* @param reserveStatusId
|
||||
* @return
|
||||
*/
|
||||
public Reserve updateStatus(String reserveStatusId) {
|
||||
this.reserveStatusId = reserveStatusId;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 취소 사유 업데이트
|
||||
*
|
||||
* @param reasonCancelContent
|
||||
* @return
|
||||
*/
|
||||
public Reserve updateReasonCancel(String reasonCancelContent) {
|
||||
this.reasonCancelContent = reasonCancelContent;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 예약 정보 업데이트
|
||||
*
|
||||
* @param updateRequestDto
|
||||
* @return
|
||||
*/
|
||||
public Reserve update(ReserveUpdateRequestDto updateRequestDto) {
|
||||
this.reserveQty = updateRequestDto.getReserveQty();
|
||||
this.reservePurposeContent = updateRequestDto.getReservePurposeContent();
|
||||
this.attachmentCode = updateRequestDto.getAttachmentCode();
|
||||
this.reserveStartDate = updateRequestDto.getReserveStartDate();
|
||||
this.reserveEndDate = updateRequestDto.getReserveEndDate();
|
||||
this.userId = updateRequestDto.getUserId();
|
||||
this.userEmail = updateRequestDto.getUserEmail();
|
||||
this.userContactNo = updateRequestDto.getUserContactNo();
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* create 정보 세팅
|
||||
* insert 시 필요
|
||||
*
|
||||
* @param createdDate
|
||||
* @param createdBy
|
||||
* @return
|
||||
*/
|
||||
public Reserve setCreatedInfo(LocalDateTime createdDate, String createdBy) {
|
||||
this.createdBy = createdBy;
|
||||
this.createDate = createdDate;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 예약 수량 양수, 음수 변환
|
||||
* 예약 취소 시 재고 카운트를 위해
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public Reserve conversionReserveQty() {
|
||||
this.reserveQty = (this.reserveQty * -1);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,208 @@
|
||||
package org.egovframe.cloud.reservechecksevice.domain.reserve;
|
||||
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.ToString;
|
||||
import org.egovframe.cloud.reactive.domain.BaseEntity;
|
||||
import org.egovframe.cloud.reservechecksevice.domain.location.Location;
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.annotation.Transient;
|
||||
import org.springframework.data.relational.core.mapping.Column;
|
||||
import org.springframework.data.relational.core.mapping.Table;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
import javax.validation.constraints.Size;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* org.egovframe.cloud.reserveitemservice.domain.reserveItem.ReserveItem
|
||||
*
|
||||
* 예약 물품 도메인 클래스
|
||||
*
|
||||
* @author 표준프레임워크센터 shinmj
|
||||
* @version 1.0
|
||||
* @since 2021/09/09
|
||||
*
|
||||
* <pre>
|
||||
* << 개정이력(Modification Information) >>
|
||||
*
|
||||
* 수정일 수정자 수정내용
|
||||
* ---------- -------- ---------------------------
|
||||
* 2021/09/09 shinmj 최초 생성
|
||||
* </pre>
|
||||
*/
|
||||
@Getter
|
||||
@NoArgsConstructor
|
||||
@ToString
|
||||
public class ReserveItem extends BaseEntity {
|
||||
|
||||
@Id
|
||||
@Column("reserve_item_id")
|
||||
private Long reserveItemId; // 예약 물품 id
|
||||
|
||||
@Size(max = 200)
|
||||
@NotNull
|
||||
@Column("reserve_item_name")
|
||||
private String reserveItemName; //예약 물품 명
|
||||
|
||||
@ToString.Exclude
|
||||
private Long locationId;
|
||||
|
||||
@ToString.Exclude
|
||||
@Transient
|
||||
private Location location; //지역
|
||||
|
||||
@Size(max = 20)
|
||||
@NotNull
|
||||
@Column
|
||||
private String categoryId; //예약유형 - 공통코드 reserve-category
|
||||
|
||||
@Transient
|
||||
private String categoryName;
|
||||
|
||||
@Size(max = 5)
|
||||
@NotNull
|
||||
@Column
|
||||
private Integer totalQty; //총 재고/수용인원 수
|
||||
|
||||
@Size(max = 5)
|
||||
@Column
|
||||
private Integer inventoryQty; //현재 재고/수용인원 수
|
||||
|
||||
@Column
|
||||
private LocalDateTime operationStartDate; //운영 시작 일
|
||||
|
||||
@Column
|
||||
private LocalDateTime operationEndDate; //운영 종료 일
|
||||
|
||||
@Size(max = 20)
|
||||
@NotNull
|
||||
@Column
|
||||
private String reserveMethodId; // 예약 방법 - 공통코드 reserve-method
|
||||
|
||||
@Transient
|
||||
private String reserveMethodName;
|
||||
|
||||
@Size(max = 20)
|
||||
@Column
|
||||
private String reserveMeansId; // 예약 구분 (인터넷 예약 시) - 공통코드 reserve-means
|
||||
|
||||
@Transient
|
||||
private String reserveMeansName;
|
||||
|
||||
@Column
|
||||
private LocalDateTime requestStartDate; //예약 신청 시작 일시
|
||||
|
||||
@Column
|
||||
private LocalDateTime requestEndDate; //예약 신청 종료 일시
|
||||
|
||||
@Column("period_at")
|
||||
private Boolean isPeriod; //기간 지정 가능 여부 - true: 지정 가능, false: 지정 불가
|
||||
|
||||
@Size(max = 3)
|
||||
@Column
|
||||
private Integer periodMaxCount; // 최대 예약 가능 일 수
|
||||
|
||||
@Size(max = 500)
|
||||
@Column
|
||||
private String externalUrl; //외부링크
|
||||
|
||||
@Size(max = 20)
|
||||
@NotNull
|
||||
@Column
|
||||
private String selectionMeansId; //선별 방법 - 공통코드 reserve-selection-means
|
||||
|
||||
@Transient
|
||||
private String selectionMeansName;
|
||||
|
||||
@Column("paid_at")
|
||||
private Boolean isPaid; // 유/무료 - false: 무료, true: 유료
|
||||
|
||||
@Column
|
||||
private BigDecimal usageCost; //이용 요금
|
||||
|
||||
@Column("use_at")
|
||||
private Boolean isUse; //사용여부
|
||||
|
||||
@Size(max = 4000)
|
||||
@Column("purpose_content")
|
||||
private String purpose; //용도
|
||||
|
||||
@Size(max = 500)
|
||||
@Column("item_addr")
|
||||
private String address; //주소
|
||||
|
||||
@Size(max = 20)
|
||||
@Column
|
||||
private String targetId; //이용 대상 - 공통코드 reserve-target
|
||||
|
||||
@Transient
|
||||
private String targetName;
|
||||
|
||||
@Size(max = 2000)
|
||||
@Column("excluded_content")
|
||||
private String excluded; // 사용허가 제외대상
|
||||
|
||||
@Size(max = 500)
|
||||
@Column("homepage_url")
|
||||
private String homepage; //홈페이지 주소
|
||||
|
||||
@Size(max = 50)
|
||||
@Column("contact_no")
|
||||
private String contact; //문의처
|
||||
|
||||
@Size(max = 200)
|
||||
@Column("manager_dept_name")
|
||||
private String managerDept; //담당자 소속
|
||||
|
||||
@Size(max = 200)
|
||||
@Column("manager_name")
|
||||
private String managerName; //담당자 이름
|
||||
|
||||
@Size(max = 50)
|
||||
@Column("manager_contact_no")
|
||||
private String managerContact; //담당자 연락처
|
||||
|
||||
@Builder
|
||||
public ReserveItem(Long reserveItemId, String reserveItemName, Long locationId, Location location, String categoryId, String categoryName, Integer totalQty, Integer inventoryQty, LocalDateTime operationStartDate, LocalDateTime operationEndDate, String reserveMethodId, String reserveMethodName, String reserveMeansId, String reserveMeansName, LocalDateTime requestStartDate, LocalDateTime requestEndDate, Boolean isPeriod, Integer periodMaxCount, String externalUrl, String selectionMeansId, String selectionMeansName, Boolean isPaid, BigDecimal usageCost, Boolean isUse, String purpose, String address, String targetId, String targetName, String excluded, String homepage, String contact, String managerDept, String managerName, String managerContact) {
|
||||
this.reserveItemId = reserveItemId;
|
||||
this.reserveItemName = reserveItemName;
|
||||
this.locationId = locationId;
|
||||
this.location = location;
|
||||
this.categoryId = categoryId;
|
||||
this.categoryName = categoryName;
|
||||
this.totalQty = totalQty;
|
||||
this.inventoryQty = inventoryQty;
|
||||
this.operationStartDate = operationStartDate;
|
||||
this.operationEndDate = operationEndDate;
|
||||
this.reserveMethodId = reserveMethodId;
|
||||
this.reserveMethodName = reserveMethodName;
|
||||
this.reserveMeansId = reserveMeansId;
|
||||
this.reserveMeansName = reserveMeansName;
|
||||
this.requestStartDate = requestStartDate;
|
||||
this.requestEndDate = requestEndDate;
|
||||
this.isPeriod = isPeriod;
|
||||
this.periodMaxCount = periodMaxCount;
|
||||
this.externalUrl = externalUrl;
|
||||
this.selectionMeansId = selectionMeansId;
|
||||
this.selectionMeansName = selectionMeansName;
|
||||
this.isPaid = isPaid;
|
||||
this.usageCost = usageCost;
|
||||
this.isUse = isUse;
|
||||
this.purpose = purpose;
|
||||
this.address = address;
|
||||
this.targetId = targetId;
|
||||
this.targetName = targetName;
|
||||
this.excluded = excluded;
|
||||
this.homepage = homepage;
|
||||
this.contact = contact;
|
||||
this.managerDept = managerDept;
|
||||
this.managerName = managerName;
|
||||
this.managerContact = managerContact;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
package org.egovframe.cloud.reservechecksevice.domain.reserve;
|
||||
|
||||
import org.springframework.data.r2dbc.repository.R2dbcRepository;
|
||||
|
||||
/**
|
||||
* org.egovframe.cloud.reservechecksevice.domain.reserve.ReserveRepository
|
||||
*
|
||||
* 예약 도메인 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,44 @@
|
||||
package org.egovframe.cloud.reservechecksevice.domain.reserve;
|
||||
|
||||
import org.egovframe.cloud.common.dto.RequestDto;
|
||||
import org.egovframe.cloud.reservechecksevice.api.reserve.dto.ReserveRequestDto;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* org.egovframe.cloud.reservechecksevice.domain.reserve.ReserveRepositoryCustom
|
||||
*
|
||||
* 예약 도메인 custom Repository interface
|
||||
*
|
||||
* @author 표준프레임워크센터 shinmj
|
||||
* @version 1.0
|
||||
* @since 2021/09/15
|
||||
*
|
||||
* <pre>
|
||||
* << 개정이력(Modification Information) >>
|
||||
*
|
||||
* 수정일 수정자 수정내용
|
||||
* ---------- -------- ---------------------------
|
||||
* 2021/09/15 shinmj 최초 생성
|
||||
* </pre>
|
||||
*/
|
||||
public interface ReserveRepositoryCustom {
|
||||
Flux<Reserve> search(ReserveRequestDto requestDto, Pageable pageable);
|
||||
Mono<Long> searchCount(ReserveRequestDto requestDto, Pageable pageable);
|
||||
Mono<Reserve> findReserveById(String reserveId);
|
||||
|
||||
Flux<Reserve> searchForUser(ReserveRequestDto requestDto, Pageable pageable, String userId);
|
||||
Mono<Long> searchCountForUser(ReserveRequestDto requestDto, Pageable pageable, String userId);
|
||||
|
||||
Mono<Reserve> loadRelations(Reserve reserve);
|
||||
|
||||
Flux<Reserve> findAllByReserveDate(Long reserveItemId, LocalDateTime startDate, LocalDateTime endDate);
|
||||
Flux<Reserve> findAllByReserveDateWithoutSelf(String reserveId, Long reserveItemId, LocalDateTime startDate, LocalDateTime endDate);
|
||||
Mono<Long> findAllByReserveDateWithoutSelfCount(String reserveId, Long reserveItemId, LocalDateTime startDate, LocalDateTime endDate);
|
||||
|
||||
Mono<Reserve> insert(Reserve reserve);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,296 @@
|
||||
package org.egovframe.cloud.reservechecksevice.domain.reserve;
|
||||
|
||||
import static org.springframework.data.relational.core.query.Criteria.*;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.egovframe.cloud.reservechecksevice.api.reserve.dto.ReserveRequestDto;
|
||||
import org.egovframe.cloud.reservechecksevice.client.ReserveItemServiceClient;
|
||||
import org.egovframe.cloud.reservechecksevice.client.UserServiceClient;
|
||||
import org.egovframe.cloud.reservechecksevice.client.dto.UserResponseDto;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.r2dbc.core.R2dbcEntityTemplate;
|
||||
import org.springframework.data.relational.core.query.Criteria;
|
||||
import org.springframework.data.relational.core.query.Query;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import io.github.resilience4j.circuitbreaker.CircuitBreaker;
|
||||
import io.github.resilience4j.circuitbreaker.CircuitBreakerRegistry;
|
||||
import io.github.resilience4j.reactor.circuitbreaker.operator.CircuitBreakerOperator;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
/**
|
||||
* org.egovframe.cloud.reservechecksevice.domain.reserve.ReserveRepositoryImpl
|
||||
*
|
||||
* 예약 도메인 custom repository 구현 클래스
|
||||
*
|
||||
* @author 표준프레임워크센터 shinmj
|
||||
* @version 1.0
|
||||
* @since 2021/09/15
|
||||
*
|
||||
* <pre>
|
||||
* << 개정이력(Modification Information) >>
|
||||
*
|
||||
* 수정일 수정자 수정내용
|
||||
* ---------- -------- ---------------------------
|
||||
* 2021/09/15 shinmj 최초 생성
|
||||
* </pre>
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
public class ReserveRepositoryImpl implements ReserveRepositoryCustom{
|
||||
private static final String RESERVE_ITEM_CIRCUIT_BREAKER_NAME = "reserve-item";
|
||||
private static final String USER_CIRCUIT_BREAKER_NAME = "user";
|
||||
|
||||
private final R2dbcEntityTemplate entityTemplate;
|
||||
private final ReserveItemServiceClient reserveItemServiceClient;
|
||||
private final UserServiceClient userServiceClient;
|
||||
private final CircuitBreakerRegistry circuitBreakerRegistry;
|
||||
|
||||
/**
|
||||
* 조회조건 목록 조회
|
||||
*
|
||||
* @param requestDto
|
||||
* @param pageable
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public Flux<Reserve> search(ReserveRequestDto requestDto, Pageable pageable) {
|
||||
|
||||
return entityTemplate.select(Reserve.class)
|
||||
.matching(Query.query(Criteria.from(whereQuery(requestDto)))
|
||||
.sort(Sort.by(Sort.Direction.DESC, "create_date"))
|
||||
.with(pageable))
|
||||
.all()
|
||||
.flatMap(this::loadRelations)
|
||||
.switchIfEmpty(Flux.empty());
|
||||
}
|
||||
|
||||
/**
|
||||
* 조회조건 목록 조회시 총 count 조회
|
||||
*
|
||||
* @param requestDto
|
||||
* @param pageable
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public Mono<Long> searchCount(ReserveRequestDto requestDto, Pageable pageable) {
|
||||
return entityTemplate.select(Reserve.class)
|
||||
.matching(Query.query(Criteria.from(whereQuery(requestDto)))
|
||||
.sort(Sort.by(Sort.Direction.DESC, "create_date"))
|
||||
.with(pageable))
|
||||
.count();
|
||||
}
|
||||
|
||||
/**
|
||||
* 예약정보 한건 조회시 relation 같이 조회
|
||||
*
|
||||
* @param reserveId
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public Mono<Reserve> findReserveById(String reserveId) {
|
||||
return entityTemplate.selectOne(Query.query(where("reserve_id").is(reserveId)), Reserve.class)
|
||||
.flatMap(this::loadRelations)
|
||||
.switchIfEmpty(Mono.empty());
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 사용자 예약 목록 조회
|
||||
*
|
||||
* @param requestDto
|
||||
* @param pageable
|
||||
* @param userId
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public Flux<Reserve> searchForUser(ReserveRequestDto requestDto, Pageable pageable, String userId) {
|
||||
Criteria where = Criteria.from(whereQuery(requestDto));
|
||||
return entityTemplate.select(Reserve.class)
|
||||
.matching(Query.query(where.and(where("user_id").is(userId)))
|
||||
.sort(Sort.by(Sort.Direction.DESC, "create_date"))
|
||||
.with(pageable))
|
||||
.all()
|
||||
.flatMap(this::loadRelations)
|
||||
.switchIfEmpty(Flux.empty());
|
||||
}
|
||||
|
||||
/**
|
||||
* 사용자 예약 목록 건수 조회
|
||||
*
|
||||
* @param requestDto
|
||||
* @param pageable
|
||||
* @param userId
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public Mono<Long> searchCountForUser(ReserveRequestDto requestDto, Pageable pageable, String userId) {
|
||||
Criteria where = Criteria.from(whereQuery(requestDto));
|
||||
return entityTemplate.select(Reserve.class)
|
||||
.matching(Query.query(where.and(where("user_id").is(userId)))
|
||||
.sort(Sort.by(Sort.Direction.DESC, "create_date"))
|
||||
.with(pageable))
|
||||
.count();
|
||||
}
|
||||
|
||||
/**
|
||||
* relation 조회
|
||||
*
|
||||
* @param reserve
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public Mono<Reserve> loadRelations(final Reserve reserve) {
|
||||
//load user
|
||||
Mono<Reserve> mono = Mono.just(reserve)
|
||||
.zipWith(findUserByUserId(reserve.getUserId()))
|
||||
.map(tuple -> tuple.getT1().setUser(tuple.getT2()))
|
||||
.switchIfEmpty(Mono.just(reserve));
|
||||
|
||||
//load reserveItem
|
||||
mono = mono.zipWith(findReserveItemWithRelation(reserve.getReserveItemId()))
|
||||
.map(tuple -> tuple.getT1().setReserveItem(tuple.getT2()))
|
||||
.switchIfEmpty(Mono.just(reserve));
|
||||
|
||||
return mono;
|
||||
}
|
||||
|
||||
/**
|
||||
* 조회 기간에 예약된 건 조회
|
||||
*
|
||||
* @param reserveItemId
|
||||
* @param startDate
|
||||
* @param endDate
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public Flux<Reserve> findAllByReserveDate(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)
|
||||
))
|
||||
.all();
|
||||
}
|
||||
|
||||
/**
|
||||
* 조회 기간에 예약된 건 조회
|
||||
* 현 예약건은 제외
|
||||
*
|
||||
* @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();
|
||||
}
|
||||
|
||||
/**
|
||||
* 예약 insert
|
||||
* pk(reserveId)를 서비스에서 생성하여 insert 하기 위함.
|
||||
*
|
||||
* @param reserve
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public Mono<Reserve> insert(Reserve reserve) {
|
||||
return entityTemplate.insert(reserve);
|
||||
}
|
||||
|
||||
/**
|
||||
* 예약 물품 정보 조회
|
||||
*
|
||||
* @param reserveItemId
|
||||
* @return
|
||||
*/
|
||||
private Mono<ReserveItem> findReserveItemWithRelation(Long reserveItemId) {
|
||||
CircuitBreaker circuitBreaker = circuitBreakerRegistry.circuitBreaker(RESERVE_ITEM_CIRCUIT_BREAKER_NAME);
|
||||
|
||||
return reserveItemServiceClient.findByIdWithRelations(reserveItemId)
|
||||
.transform(CircuitBreakerOperator.of(circuitBreaker))
|
||||
.onErrorResume(throwable -> Mono.empty())
|
||||
.switchIfEmpty(Mono.empty())
|
||||
.flatMap(reserveItemRelationResponseDto -> Mono.just(reserveItemRelationResponseDto.toEntity()));
|
||||
}
|
||||
|
||||
/**
|
||||
* 예약자 정보 조회
|
||||
*
|
||||
* @param userId
|
||||
* @return
|
||||
*/
|
||||
private Mono<UserResponseDto> findUserByUserId(String userId ) {
|
||||
CircuitBreaker circuitBreaker = circuitBreakerRegistry.circuitBreaker(USER_CIRCUIT_BREAKER_NAME);
|
||||
return userServiceClient.findByUserId(userId)
|
||||
.transform(CircuitBreakerOperator.of(circuitBreaker))
|
||||
.onErrorResume(throwable -> Mono.empty());
|
||||
}
|
||||
|
||||
/**
|
||||
* 조회조건 쿼리
|
||||
*
|
||||
* @param requestDto
|
||||
* @return
|
||||
*/
|
||||
private List<Criteria> whereQuery(ReserveRequestDto requestDto) {
|
||||
List<Criteria>criteriaList = new ArrayList<>();
|
||||
|
||||
if (requestDto.getLocationId() != null) {
|
||||
criteriaList.add(where("location_id").is(requestDto.getLocationId()));
|
||||
}
|
||||
|
||||
if (requestDto.getCategoryId() != null) {
|
||||
criteriaList.add(where("category_id").is(requestDto.getCategoryId()));
|
||||
}
|
||||
|
||||
if (StringUtils.hasText(requestDto.getKeyword())) {
|
||||
if ("item".equals(requestDto.getKeywordType())) {
|
||||
criteriaList.add(where("reserve_item_id").like(likeText(requestDto.getKeyword())));
|
||||
}
|
||||
}
|
||||
return criteriaList;
|
||||
}
|
||||
|
||||
/**
|
||||
* like 검색
|
||||
*
|
||||
* @param keyword
|
||||
* @return
|
||||
*/
|
||||
private String likeText(String keyword) {
|
||||
return "%" + keyword + "%";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package org.egovframe.cloud.reservechecksevice.domain.reserve;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
/**
|
||||
* org.egovframe.cloud.reservechecksevice.domain.reserve.ReserveStatus
|
||||
*
|
||||
* 예약 상태 enum class
|
||||
*
|
||||
* @author 표준프레임워크센터 shinmj
|
||||
* @version 1.0
|
||||
* @since 2021/09/15
|
||||
*
|
||||
* <pre>
|
||||
* << 개정이력(Modification Information) >>
|
||||
*
|
||||
* 수정일 수정자 수정내용
|
||||
* ---------- -------- ---------------------------
|
||||
* 2021/09/15 shinmj 최초 생성
|
||||
* </pre>
|
||||
*/
|
||||
@Getter
|
||||
@RequiredArgsConstructor
|
||||
public enum ReserveStatus {
|
||||
REQUEST("request", "예약 신청"),
|
||||
APPROVE("approve", "예약 승인"),
|
||||
CANCEL("cancel", "예약 취소"),
|
||||
DONE("done", "완료");
|
||||
|
||||
private final String key;
|
||||
private final String title;
|
||||
|
||||
public boolean isEquals(String status) {
|
||||
return this.getKey().equals(status);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,626 @@
|
||||
package org.egovframe.cloud.reservechecksevice.service.reserve;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
import org.egovframe.cloud.common.domain.Role;
|
||||
import org.egovframe.cloud.common.dto.AttachmentEntityMessage;
|
||||
import org.egovframe.cloud.common.exception.BusinessMessageException;
|
||||
import org.egovframe.cloud.reactive.service.ReactiveAbstractService;
|
||||
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.ReserveRequestDto;
|
||||
import org.egovframe.cloud.reservechecksevice.api.reserve.dto.ReserveResponseDto;
|
||||
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.dto.ReserveItemResponseDto;
|
||||
import org.egovframe.cloud.reservechecksevice.domain.reserve.Category;
|
||||
import org.egovframe.cloud.reservechecksevice.domain.reserve.Reserve;
|
||||
import org.egovframe.cloud.reservechecksevice.domain.reserve.ReserveRepository;
|
||||
import org.egovframe.cloud.reservechecksevice.domain.reserve.ReserveStatus;
|
||||
import org.springframework.cloud.stream.function.StreamBridge;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageImpl;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
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 io.github.resilience4j.circuitbreaker.CircuitBreakerRegistry;
|
||||
import io.github.resilience4j.reactor.circuitbreaker.operator.CircuitBreakerOperator;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
/**
|
||||
* org.egovframe.cloud.reservechecksevice.service.reserve.ReserveService
|
||||
*
|
||||
* 예약 service 클래스
|
||||
*
|
||||
* @author 표준프레임워크센터 shinmj
|
||||
* @version 1.0
|
||||
* @since 2021/09/15
|
||||
*
|
||||
* <pre>
|
||||
* << 개정이력(Modification Information) >>
|
||||
*
|
||||
* 수정일 수정자 수정내용
|
||||
* ---------- -------- ---------------------------
|
||||
* 2021/09/15 shinmj 최초 생성
|
||||
* </pre>
|
||||
*/
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
@Transactional
|
||||
@Service
|
||||
public class ReserveService extends ReactiveAbstractService {
|
||||
private static final String RESERVE_ITEM_CIRCUIT_BREAKER_NAME = "reserve-item";
|
||||
private static final String CHECK_RESERVE_MEANS = "realtime";
|
||||
|
||||
private final ReserveRepository reserveRepository;
|
||||
private final ReserveItemServiceClient reserveItemServiceClient;
|
||||
private final CircuitBreakerRegistry circuitBreakerRegistry;
|
||||
private final StreamBridge streamBridge;
|
||||
|
||||
/**
|
||||
* entity -> dto 변환
|
||||
*
|
||||
* @param reserve
|
||||
* @return
|
||||
*/
|
||||
private Mono<ReserveResponseDto> convertReserveResponseDto(Reserve reserve) {
|
||||
return Mono.just(ReserveResponseDto.builder()
|
||||
.entity(reserve)
|
||||
.build());
|
||||
}
|
||||
|
||||
/**
|
||||
* entity -> 목록 dto 변환
|
||||
*
|
||||
* @param reserve
|
||||
* @return
|
||||
*/
|
||||
private Mono<ReserveListResponseDto> convertReserveListResponseDto(Reserve reserve) {
|
||||
return Mono.just(ReserveListResponseDto.builder()
|
||||
.entity(reserve)
|
||||
.build());
|
||||
}
|
||||
|
||||
/**
|
||||
* 현재 로그인 사용자가 관리자인지 체크
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private Mono<Boolean> getIsAdmin() {
|
||||
return ReactiveSecurityContextHolder.getContext()
|
||||
.map(SecurityContext::getAuthentication)
|
||||
.filter(Authentication::isAuthenticated)
|
||||
.map(Authentication::getAuthorities)
|
||||
.map(grantedAuthorities -> {
|
||||
List<SimpleGrantedAuthority> authorities =
|
||||
new ArrayList<>((Collection<? extends SimpleGrantedAuthority>) grantedAuthorities);
|
||||
SimpleGrantedAuthority adminRole = new SimpleGrantedAuthority(Role.ADMIN.getKey());
|
||||
return authorities.contains(adminRole);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 현재 로그인 사용자 id
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private Mono<String> getUserId() {
|
||||
return ReactiveSecurityContextHolder.getContext()
|
||||
.map(SecurityContext::getAuthentication)
|
||||
.filter(Authentication::isAuthenticated)
|
||||
.map(Authentication::getPrincipal)
|
||||
.map(String.class::cast);
|
||||
}
|
||||
|
||||
/**
|
||||
* 목록 조회
|
||||
*
|
||||
* @param requestDto
|
||||
* @param pageable
|
||||
* @return
|
||||
*/
|
||||
@Transactional(readOnly = true)
|
||||
public Mono<Page<ReserveListResponseDto>> search(ReserveRequestDto requestDto, Pageable pageable) {
|
||||
return reserveRepository.search(requestDto, pageable)
|
||||
.switchIfEmpty(Flux.empty())
|
||||
.flatMap(this::convertReserveListResponseDto)
|
||||
.collectList()
|
||||
.zipWith(reserveRepository.searchCount(requestDto, pageable))
|
||||
.flatMap(tuple -> Mono.just(new PageImpl<>(tuple.getT1(), pageable, tuple.getT2())));
|
||||
}
|
||||
|
||||
/**
|
||||
* 한건 조회 dto return
|
||||
*
|
||||
* @param reserveId
|
||||
* @return
|
||||
*/
|
||||
@Transactional(readOnly = true)
|
||||
public Mono<ReserveResponseDto> findReserveById(String reserveId) {
|
||||
return reserveRepository.findReserveById(reserveId)
|
||||
.switchIfEmpty(monoResponseStatusEntityNotFoundException(reserveId))
|
||||
.flatMap(this::convertReserveResponseDto);
|
||||
}
|
||||
|
||||
/**
|
||||
* 사용자용 예약 목록 조회 (로그인 사용자의 예약정보만 조회)
|
||||
*
|
||||
* @param userId
|
||||
* @param requestDto
|
||||
* @param pageable
|
||||
* @return
|
||||
*/
|
||||
@Transactional(readOnly = true)
|
||||
public Mono<Page<ReserveListResponseDto>> searchForUser(String userId, ReserveRequestDto requestDto, Pageable pageable) {
|
||||
return reserveRepository.searchForUser(requestDto, pageable, userId)
|
||||
.switchIfEmpty(Flux.empty())
|
||||
.flatMap(this::convertReserveListResponseDto)
|
||||
.collectList()
|
||||
.zipWith(reserveRepository.searchCountForUser(requestDto, pageable, userId))
|
||||
.flatMap(tuple -> Mono.just(new PageImpl<>(tuple.getT1(), pageable, tuple.getT2())));
|
||||
}
|
||||
|
||||
/**
|
||||
* 예약 정보 취소
|
||||
*
|
||||
* @param reserveId
|
||||
* @param cancelRequestDto
|
||||
* @return
|
||||
*/
|
||||
public Mono<Void> cancel(String reserveId, ReserveCancelRequestDto cancelRequestDto) {
|
||||
return getIsAdmin().flatMap(isAdmin -> {
|
||||
if (isAdmin) {
|
||||
return reserveCancel(reserveId, cancelRequestDto);
|
||||
}
|
||||
return findById(reserveId)
|
||||
.zipWith(getUserId())
|
||||
.flatMap(tuple -> {
|
||||
if (tuple.getT1().getUserId().equals(tuple.getT2())) {
|
||||
return Mono.just(tuple.getT1());
|
||||
}
|
||||
//해당 예약은 취소할 수 없습니다.
|
||||
return Mono.error(new BusinessMessageException(getMessage("valid.cant_cancel")));
|
||||
})
|
||||
.onErrorResume(throwable -> Mono.error(throwable))
|
||||
.flatMap(reserve -> reserveCancel(reserveId, cancelRequestDto));
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 예약 상태 취소로 변경
|
||||
*
|
||||
* @param reserveId
|
||||
* @param cancelRequestDto
|
||||
* @return
|
||||
*/
|
||||
private Mono<Void> reserveCancel(String reserveId, ReserveCancelRequestDto cancelRequestDto) {
|
||||
return findById(reserveId)
|
||||
.map(reserve -> {
|
||||
if (ReserveStatus.DONE.isEquals(reserve.getReserveStatusId())) {
|
||||
//해당 예약은 이미 실행되어 취소할 수 없습니다.
|
||||
throw new BusinessMessageException(getMessage("valid.cant_cancel_because_done"));
|
||||
}else {
|
||||
return reserve.updateStatus(ReserveStatus.CANCEL.getKey())
|
||||
.updateReasonCancel(cancelRequestDto.getReasonCancelContent());
|
||||
}
|
||||
})
|
||||
.flatMap(reserve -> Mono.just(reserve.conversionReserveQty()))
|
||||
.flatMap(this::updateInventory)
|
||||
.onErrorResume(throwable -> Mono.error(throwable))
|
||||
.flatMap(reserve -> Mono.just(reserve.conversionReserveQty()))
|
||||
.flatMap(reserveRepository::save)
|
||||
.then();
|
||||
}
|
||||
|
||||
/**
|
||||
* 예약 정보 승인
|
||||
*
|
||||
* @param reserveId
|
||||
* @return
|
||||
*/
|
||||
public Mono<Void> approve(String reserveId) {
|
||||
return getIsAdmin()
|
||||
.flatMap(isAdmin -> {
|
||||
if (isAdmin) {
|
||||
return Mono.just(reserveId);
|
||||
}
|
||||
//관리자만 승인할 수 있습니다.
|
||||
return Mono.error(new BusinessMessageException(getMessage("valid.manager_approve")));
|
||||
})
|
||||
.onErrorResume(throwable -> Mono.error(throwable))
|
||||
.flatMap(this::checkApprove)
|
||||
.onErrorResume(throwable -> Mono.error(throwable))
|
||||
.flatMap(reserveRepository::save).then();
|
||||
}
|
||||
|
||||
/**
|
||||
* 승인 전 validate check 및 교육인 경우 재고 업데이트
|
||||
*
|
||||
* @param reserveId
|
||||
* @return
|
||||
*/
|
||||
private Mono<Reserve> checkApprove(String reserveId) {
|
||||
return findById(reserveId)
|
||||
.flatMap(this::checkReserveItems)
|
||||
.onErrorResume(throwable -> Mono.error(throwable))
|
||||
.map(reserve -> reserve.updateStatus(ReserveStatus.APPROVE.getKey()))
|
||||
.flatMap(this::updateInventory);
|
||||
}
|
||||
|
||||
/**
|
||||
* 예약 물품 재고 및 예약 일자 체크
|
||||
*
|
||||
* @param reserve
|
||||
* @return
|
||||
*/
|
||||
private Mono<Reserve> checkReserveItems(Reserve reserve) {
|
||||
return reserveItemServiceClient.findById(reserve.getReserveItemId())
|
||||
.transform(CircuitBreakerOperator.of(circuitBreakerRegistry.circuitBreaker(RESERVE_ITEM_CIRCUIT_BREAKER_NAME)))
|
||||
.onErrorResume(throwable -> Mono.empty())
|
||||
.flatMap(reserveItemResponseDto -> {
|
||||
// validation check
|
||||
if (Category.SPACE.isEquals(reserveItemResponseDto.getCategoryId())) {
|
||||
return this.checkSpace(reserveItemResponseDto, reserve);
|
||||
}else if (Category.EQUIPMENT.isEquals(reserveItemResponseDto.getCategoryId())) {
|
||||
return this.checkEquipment(reserveItemResponseDto, reserve);
|
||||
}else if (Category.EDUCATION.isEquals(reserveItemResponseDto.getCategoryId())) {
|
||||
return this.checkEducation(reserveItemResponseDto, reserve);
|
||||
}
|
||||
return Mono.just(reserve);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 예약 날짜 validation
|
||||
*
|
||||
* @param reserveItem
|
||||
* @param reserve
|
||||
* @return
|
||||
*/
|
||||
private Mono<Reserve> checkReserveDate(ReserveItemResponseDto reserveItem, Reserve reserve) {
|
||||
LocalDateTime startDate = reserveItem.getReserveMeansId().equals(CHECK_RESERVE_MEANS) ?
|
||||
reserveItem.getRequestStartDate() : reserveItem.getOperationStartDate();
|
||||
LocalDateTime endDate = reserveItem.getReserveMeansId().equals(CHECK_RESERVE_MEANS) ?
|
||||
reserveItem.getRequestEndDate() : reserveItem.getOperationEndDate();
|
||||
|
||||
if (reserve.getReserveStartDate().isBefore(startDate)) {
|
||||
//{0}이 {1} 보다 빠릅니다. 시작일, 운영/예약 시작일
|
||||
return Mono.error(new BusinessMessageException(getMessage("valid.to_be_fast.format", new Object[]{getMessage("common.start_date"),
|
||||
getMessage("reserve_item.operation")+getMessage("reserve")+" "+getMessage("common.start_date")})));
|
||||
}
|
||||
|
||||
if (reserve.getReserveEndDate().isAfter(endDate)) {
|
||||
//{0}이 {1} 보다 늦습니다. 종료일, 운영/예약 종료일
|
||||
return Mono.error(new BusinessMessageException(getMessage("valid.to_be_slow.format", new Object[]{getMessage("common.end_date"),
|
||||
getMessage("reserve_item.operation")+getMessage("reserve")+" "+getMessage("common.end_date")})));
|
||||
}
|
||||
|
||||
if (reserveItem.getIsPeriod()) {
|
||||
long between = ChronoUnit.DAYS.between(reserve.getReserveStartDate(), reserve.getReserveEndDate());
|
||||
if (reserveItem.getPeriodMaxCount() < between) {
|
||||
//최대 예약 가능 일수보다 예약기간이 깁니다. (최대 예약 가능일 수 : {0})
|
||||
return Mono.error(new BusinessMessageException(getMessage("valid.reserve_period", new Object[]{reserveItem.getPeriodMaxCount()})));
|
||||
}
|
||||
}
|
||||
|
||||
return Mono.just(reserve);
|
||||
}
|
||||
|
||||
/**
|
||||
* 공간 예약 시 예약 날짜에 다른 예약이 있는지 체크
|
||||
*
|
||||
* @param reserveItem
|
||||
* @param reserve
|
||||
* @return
|
||||
*/
|
||||
private Mono<Reserve> checkSpace(ReserveItemResponseDto reserveItem, Reserve reserve) {
|
||||
return this.checkReserveDate(reserveItem, reserve)
|
||||
.flatMap(isValid -> reserveRepository.findAllByReserveDateWithoutSelfCount(
|
||||
reserve.getReserveId(),
|
||||
reserveItem.getReserveItemId(),
|
||||
reserve.getReserveStartDate(),
|
||||
reserve.getReserveEndDate())
|
||||
.flatMap(count -> {
|
||||
if (count > 0) {
|
||||
//"해당 날짜에는 예약할 수 없습니다."
|
||||
return Mono.error(new BusinessMessageException(getMessage("valid.reserve_date")));
|
||||
}
|
||||
return Mono.just(reserve);
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 장비 예약 시 예약 날짜에 예약 가능한 재고 체크
|
||||
*
|
||||
* @param reserveItem
|
||||
* @param reserve
|
||||
* @return
|
||||
*/
|
||||
private Mono<Reserve> checkEquipment(ReserveItemResponseDto reserveItem, Reserve reserve) {
|
||||
return this.checkReserveDate(reserveItem, reserve)
|
||||
.flatMap(entity -> this.getMaxByReserveDateWithoutSelf(
|
||||
entity.getReserveId(),
|
||||
reserveItem.getReserveItemId(),
|
||||
entity.getReserveStartDate(),
|
||||
entity.getReserveEndDate())
|
||||
.flatMap(max -> {
|
||||
if ((reserveItem.getTotalQty() - max) < reserve.getReserveQty()) {
|
||||
return Mono.just(false);
|
||||
}
|
||||
return Mono.just(true);
|
||||
})
|
||||
.flatMap(isValid -> {
|
||||
if (!isValid) {
|
||||
//해당 날짜에 예약할 수 있는 재고수량이 없습니다.
|
||||
return Mono.error(new BusinessMessageException(getMessage("valid.reserve_count")));
|
||||
}
|
||||
return Mono.just(reserve);
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 교육 예약 시 재고 체크
|
||||
*
|
||||
* @param reserveItem
|
||||
* @param reserve
|
||||
* @return
|
||||
*/
|
||||
private Mono<Reserve> checkEducation(ReserveItemResponseDto reserveItem, Reserve reserve) {
|
||||
return Mono.just(reserveItem)
|
||||
.flatMap(reserveItemResponseDto -> {
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
LocalDateTime startDate = reserveItemResponseDto.getReserveMeansId().equals(CHECK_RESERVE_MEANS) ?
|
||||
reserveItemResponseDto.getRequestStartDate() : reserveItemResponseDto.getOperationStartDate();
|
||||
LocalDateTime endDate = reserveItemResponseDto.getReserveMeansId().equals(CHECK_RESERVE_MEANS) ?
|
||||
reserveItemResponseDto.getRequestEndDate() : reserveItemResponseDto.getOperationEndDate();
|
||||
|
||||
if (!(now.isAfter(startDate) && now.isBefore(endDate))) {
|
||||
//해당 날짜에는 예약할 수 없습니다.
|
||||
return Mono.error(new BusinessMessageException(getMessage("valid.reserve_date")));
|
||||
}
|
||||
|
||||
if (reserveItemResponseDto.getInventoryQty() <= 0) {
|
||||
//"예약이 마감되었습니다."
|
||||
return Mono.error(new BusinessMessageException(getMessage("valid.reserve_close")));
|
||||
}
|
||||
|
||||
if (reserveItemResponseDto.getInventoryQty() < reserve.getReserveQty()) {
|
||||
//예약가능한 인원이 부족합니다. (남은 인원 : {0})
|
||||
return Mono.error(new BusinessMessageException(getMessage("valid.reserve_number_of_people", new Object[]{reserveItemResponseDto.getInventoryQty()})));
|
||||
}
|
||||
return Mono.just(reserve);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 예약 정보 수정
|
||||
*
|
||||
* @param reserveId
|
||||
* @return
|
||||
*/
|
||||
public Mono<Reserve> update(String reserveId, ReserveUpdateRequestDto updateRequestDto) {
|
||||
return getIsAdmin().flatMap(isAdmin -> {
|
||||
if (isAdmin) {
|
||||
return updateReserve(reserveId, updateRequestDto);
|
||||
}
|
||||
return updateReserveForUser(reserveId, updateRequestDto);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 사용자 예약 수정
|
||||
*
|
||||
* @param reserveId
|
||||
* @param updateRequestDto
|
||||
* @return
|
||||
*/
|
||||
private Mono<Reserve> updateReserveForUser(String reserveId, ReserveUpdateRequestDto updateRequestDto) {
|
||||
return findById(reserveId)
|
||||
.zipWith(getUserId())
|
||||
.map(tuple -> {
|
||||
if (!tuple.getT1().getUserId().equals(tuple.getT2())) {
|
||||
//"해당 예약은 수정할 수 없습니다."
|
||||
throw new BusinessMessageException(getMessage("valid.reserve_not_update"));
|
||||
}
|
||||
|
||||
if (!ReserveStatus.REQUEST.getKey().equals(tuple.getT1().getReserveStatusId())) {
|
||||
//예약 신청 상태인 경우에만 수정 가능합니다.
|
||||
throw new BusinessMessageException(getMessage("valid.reserve_not_update_status"));
|
||||
}
|
||||
|
||||
return tuple.getT1().update(updateRequestDto);
|
||||
})
|
||||
.flatMap(this::checkReserveItems)
|
||||
.onErrorResume(throwable -> Mono.error(throwable))
|
||||
.flatMap(this::updateInventory)
|
||||
.onErrorResume(throwable -> Mono.error(throwable))
|
||||
.flatMap(reserveRepository::save);
|
||||
}
|
||||
|
||||
/**
|
||||
* 관리자 예약 수정
|
||||
*
|
||||
* @param reserveId
|
||||
* @param updateRequestDto
|
||||
* @return
|
||||
*/
|
||||
private Mono<Reserve> updateReserve(String reserveId, ReserveUpdateRequestDto updateRequestDto) {
|
||||
return findById(reserveId)
|
||||
.map(reserve -> {
|
||||
if (!ReserveStatus.REQUEST.getKey().equals(reserve.getReserveStatusId())) {
|
||||
//예약 신청 상태인 경우에만 수정 가능합니다.
|
||||
throw new BusinessMessageException(getMessage("valid.reserve_not_update_status"));
|
||||
}
|
||||
return reserve.update(updateRequestDto);
|
||||
})
|
||||
.flatMap(this::checkReserveItems)
|
||||
.onErrorResume(throwable -> Mono.error(throwable))
|
||||
.flatMap(this::updateInventory)
|
||||
.onErrorResume(throwable -> Mono.error(throwable))
|
||||
.flatMap(reserveRepository::save);
|
||||
}
|
||||
|
||||
/**
|
||||
* 한건 정보 조회 entity return
|
||||
*
|
||||
* @param reserveId
|
||||
* @return
|
||||
*/
|
||||
private Mono<Reserve> findById(String reserveId) {
|
||||
return reserveRepository.findById(reserveId)
|
||||
.switchIfEmpty(monoResponseStatusEntityNotFoundException(reserveId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 관리자 예약 신청
|
||||
* 관리자의 경우 실시간이어도 이벤트 스트림 거치지 않고 바로 예약 처리
|
||||
*
|
||||
* @param saveRequestDto
|
||||
* @return
|
||||
*/
|
||||
public Mono<ReserveResponseDto> create(ReserveSaveRequestDto saveRequestDto) {
|
||||
return Mono.just(saveRequestDto)
|
||||
.map(dto -> {
|
||||
String uuid = UUID.randomUUID().toString();
|
||||
dto.setReserveId(uuid);
|
||||
return dto.toEntity();
|
||||
})
|
||||
.zipWith(getUserId())
|
||||
.flatMap(tuple -> Mono.just(tuple.getT1().setCreatedInfo(LocalDateTime.now(), tuple.getT2())))
|
||||
.flatMap(this::checkReserveItems)
|
||||
.onErrorResume(throwable -> Mono.error(throwable))
|
||||
.flatMap(this::updateInventory)
|
||||
.onErrorResume(throwable -> Mono.error(throwable))
|
||||
.flatMap(reserveRepository::insert)
|
||||
.flatMap(reserveRepository::loadRelations)
|
||||
.doOnNext(reserve -> sendAttachmentEntityInfo(streamBridge,
|
||||
AttachmentEntityMessage.builder()
|
||||
.attachmentCode(reserve.getAttachmentCode())
|
||||
.entityName(reserve.getClass().getName())
|
||||
.entityId(reserve.getReserveId())
|
||||
.build()))
|
||||
.flatMap(this::convertReserveResponseDto);
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 예약 정보 저장 시 재고 변경
|
||||
*
|
||||
* @param reserve
|
||||
* @return
|
||||
*/
|
||||
private Mono<Reserve> updateInventory(Reserve reserve) {
|
||||
return Mono.just(reserve)
|
||||
.flatMap(reserve1 -> {
|
||||
if (!Category.EDUCATION.isEquals(reserve1.getCategoryId())) {
|
||||
return Mono.just(reserve1);
|
||||
}
|
||||
// return reserveItemServiceClient.updateInventory(reserve.getReserveItemId(), reserve.getReserveQty())
|
||||
// .transform(CircuitBreakerOperator.of(circuitBreakerRegistry.circuitBreaker(RESERVE_ITEM_CIRCUIT_BREAKER_NAME)))
|
||||
// .onErrorResume(throwable -> Mono.just(false))
|
||||
// .flatMap(isSuccess -> {
|
||||
// if (isSuccess) {
|
||||
// return Mono.just(reserve);
|
||||
// }
|
||||
// //재고 업데이트에 실패했습니다.
|
||||
// return Mono.error(new BusinessMessageException(getMessage("msg.inventory_failed")));
|
||||
// });
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 예약 물품별 기간안에 있는 예약된 수량 max 조회
|
||||
*
|
||||
* @param reserveItemId
|
||||
* @param startDate
|
||||
* @param endDate
|
||||
* @return
|
||||
*/
|
||||
public Mono<Integer> countInventory(Long reserveItemId, LocalDateTime startDate, LocalDateTime endDate) {
|
||||
return reserveItemServiceClient.findById(reserveItemId)
|
||||
.transform(CircuitBreakerOperator.of(circuitBreakerRegistry.circuitBreaker(RESERVE_ITEM_CIRCUIT_BREAKER_NAME)))
|
||||
.onErrorResume(throwable -> Mono.empty())
|
||||
.zipWith(getMaxByReserveDate(reserveItemId, startDate, endDate))
|
||||
.flatMap(tuple -> Mono.just(tuple.getT1().getTotalQty() - tuple.getT2()));
|
||||
}
|
||||
|
||||
/**
|
||||
* 예약물품에 대해 날짜별 예약된 수량 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());
|
||||
return countMax(reserveFlux, startDate, endDate);
|
||||
}
|
||||
|
||||
/**
|
||||
* 예약물품에 대해 날짜별 예약된 수량 max 조회
|
||||
*
|
||||
* @param reserveItemId
|
||||
* @param startDate
|
||||
* @param endDate
|
||||
* @return
|
||||
*/
|
||||
private Mono<Integer> getMaxByReserveDate(Long reserveItemId, LocalDateTime startDate, LocalDateTime endDate) {
|
||||
Flux<Reserve> reserveFlux = reserveRepository.findAllByReserveDate(reserveItemId, startDate, endDate)
|
||||
.switchIfEmpty(Flux.empty());
|
||||
return countMax(reserveFlux, startDate, endDate);
|
||||
}
|
||||
|
||||
/**
|
||||
* get max
|
||||
*
|
||||
* @param reserveFlux
|
||||
* @param startDate
|
||||
* @param endDate
|
||||
* @return
|
||||
*/
|
||||
private Mono<Integer> countMax(Flux<Reserve> reserveFlux, LocalDateTime startDate, LocalDateTime endDate) {
|
||||
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();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,176 @@
|
||||
package org.egovframe.cloud.reservechecksevice.validator;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.validation.ConstraintValidator;
|
||||
import javax.validation.ConstraintValidatorContext;
|
||||
|
||||
import org.egovframe.cloud.common.util.MessageUtil;
|
||||
import org.egovframe.cloud.reservechecksevice.validator.annotation.ReserveSaveValid;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/**
|
||||
* org.egovframe.cloud.reservechecksevice.validator.ReserveSaveValidator
|
||||
*
|
||||
* 예약 신청 시 validation check를 하기 위한 custom validator
|
||||
*
|
||||
* @author 표준프레임워크센터 shinmj
|
||||
* @version 1.0
|
||||
* @since 2021/09/23
|
||||
*
|
||||
* <pre>
|
||||
* << 개정이력(Modification Information) >>
|
||||
*
|
||||
* 수정일 수정자 수정내용
|
||||
* ---------- -------- ---------------------------
|
||||
* 2021/09/23 shinmj 최초 생성
|
||||
* </pre>
|
||||
*/
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
public class ReserveSaveValidator implements ConstraintValidator<ReserveSaveValid, Object> {
|
||||
|
||||
@Resource(
|
||||
name = "messageUtil"
|
||||
)
|
||||
protected MessageUtil messageUtil;
|
||||
|
||||
private String message;
|
||||
|
||||
|
||||
@Override
|
||||
public void initialize(ReserveSaveValid constraintAnnotation) {
|
||||
message = constraintAnnotation.message();
|
||||
}
|
||||
|
||||
/**
|
||||
* 예약 신청 시 비지니스 로직에 의한 validation check
|
||||
*
|
||||
* @param value
|
||||
* @param context
|
||||
* @return
|
||||
*/
|
||||
@SneakyThrows
|
||||
@Override
|
||||
public boolean isValid(Object value, ConstraintValidatorContext context) {
|
||||
boolean fieldValid = true;
|
||||
|
||||
String categoryId = String.valueOf(getFieldValue(value, "categoryId"));
|
||||
if ("education".equals(categoryId)) {
|
||||
//교육인 경우
|
||||
//신청인원
|
||||
fieldValid = checkReserveQty(value, context);
|
||||
|
||||
}else if ("equipment".equals(categoryId)) {
|
||||
//장비인 경우
|
||||
//신청일자(기간), 신청수량
|
||||
fieldValid = checkReserveDate(value, context);
|
||||
fieldValid = checkReserveQty(value, context);
|
||||
|
||||
}else if ("place".equals(categoryId)) {
|
||||
//공간인 경우
|
||||
//신청일자(기간)
|
||||
fieldValid = checkReserveDate(value, context);
|
||||
}
|
||||
|
||||
return fieldValid;
|
||||
}
|
||||
|
||||
/**
|
||||
* 예약 수량 체크
|
||||
*
|
||||
* @param value
|
||||
* @param context
|
||||
* @return
|
||||
*/
|
||||
@SneakyThrows
|
||||
private boolean checkReserveQty(Object value, ConstraintValidatorContext context) {
|
||||
if (isNull(value, "reserveQty")) {
|
||||
context.disableDefaultConstraintViolation();
|
||||
//예약 수량 값은 필수 입니다.
|
||||
context.buildConstraintViolationWithTemplate(messageUtil.getMessage("reserve")+" "+messageUtil.getMessage("reserve.count") + messageUtil.getMessage("valid.required"))
|
||||
.addPropertyNode("reserveQty")
|
||||
.addConstraintViolation();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 예약 신청 기간 체크
|
||||
*
|
||||
* @param value
|
||||
* @param context
|
||||
* @return
|
||||
*/
|
||||
@SneakyThrows
|
||||
private boolean checkReserveDate(Object value, ConstraintValidatorContext context) {
|
||||
// 예약 신청 기간 필수
|
||||
if (isNull(value, "reserveStartDate")) {
|
||||
context.disableDefaultConstraintViolation();
|
||||
// 예약 신청 시작일 값은 필수 입니다.
|
||||
context.buildConstraintViolationWithTemplate(messageUtil.getMessage("reserve_item.request")+" "+messageUtil.getMessage("common.start_datetime") + messageUtil.getMessage("valid.required"))
|
||||
.addPropertyNode("reserveStartDate")
|
||||
.addConstraintViolation();
|
||||
return false;
|
||||
} else if (isNull(value, "reserveEndDate")) {
|
||||
context.disableDefaultConstraintViolation();
|
||||
// 예약 신청 종료일 값은 필수 입니다.
|
||||
context.buildConstraintViolationWithTemplate(messageUtil.getMessage("reserve_item.request")+" "+messageUtil.getMessage("common.end_datetime") + messageUtil.getMessage("valid.required"))
|
||||
.addPropertyNode("reserveEndDate")
|
||||
.addConstraintViolation();
|
||||
return false;
|
||||
}else {
|
||||
// 예약 시작일, 종료일 체크
|
||||
LocalDateTime reserveStartDate = (LocalDateTime) getFieldValue(value, "reserveStartDate");
|
||||
LocalDateTime reserveEndDate = (LocalDateTime) getFieldValue(value, "reserveEndDate");
|
||||
if (reserveStartDate.isAfter(reserveEndDate)) {
|
||||
context.disableDefaultConstraintViolation();
|
||||
//시작일, 종료일, {0}이 {1}보다 늦습니다.
|
||||
context.buildConstraintViolationWithTemplate(messageUtil.getMessage("valid.to_be_slow.format", new Object[]{messageUtil.getMessage("common.start_date"), messageUtil.getMessage("common.end_date")}))
|
||||
.addPropertyNode("reserveStartDate")
|
||||
.addConstraintViolation();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 해당하는 field의 값 조회
|
||||
*
|
||||
* @param object
|
||||
* @param fieldName
|
||||
* @return
|
||||
* @throws NoSuchFieldException
|
||||
* @throws IllegalAccessException
|
||||
*/
|
||||
private Object getFieldValue(Object object, String fieldName) throws NoSuchFieldException, IllegalAccessException {
|
||||
Class<?> clazz = object.getClass();
|
||||
Field field = clazz.getDeclaredField(fieldName);
|
||||
field.setAccessible(true);
|
||||
return field.get(object);
|
||||
}
|
||||
|
||||
/**
|
||||
* 해당하는 Field가 null인지 체크
|
||||
*
|
||||
* @param object
|
||||
* @param fieldName
|
||||
* @return
|
||||
* @throws NoSuchFieldException
|
||||
* @throws IllegalAccessException
|
||||
*/
|
||||
private boolean isNull(Object object, String fieldName) throws NoSuchFieldException, IllegalAccessException {
|
||||
Class<?> clazz = object.getClass();
|
||||
Field field = clazz.getDeclaredField(fieldName);
|
||||
field.setAccessible(true);
|
||||
return field.get(object) == null || !StringUtils.hasLength(String.valueOf(field.get(object)));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package org.egovframe.cloud.reservechecksevice.validator.annotation;
|
||||
|
||||
|
||||
import org.egovframe.cloud.reservechecksevice.validator.ReserveSaveValidator;
|
||||
|
||||
import javax.validation.Constraint;
|
||||
import javax.validation.Payload;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* org.egovframe.cloud.reservechecksevice.validator.annotation.ReserveSaveValid
|
||||
*
|
||||
* 예약 신청 시 validation check를 하기 위한 custom annotation
|
||||
*
|
||||
* @author 표준프레임워크센터 shinmj
|
||||
* @version 1.0
|
||||
* @since 2021/09/23
|
||||
*
|
||||
* <pre>
|
||||
* << 개정이력(Modification Information) >>
|
||||
*
|
||||
* 수정일 수정자 수정내용
|
||||
* ---------- -------- ---------------------------
|
||||
* 2021/09/23 shinmj 최초 생성
|
||||
* </pre>
|
||||
*/
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Constraint(validatedBy = ReserveSaveValidator.class)
|
||||
public @interface ReserveSaveValid {
|
||||
String message() default "저장할 수 없습니다.";
|
||||
Class<?>[] groups() default {};
|
||||
Class<? extends Payload>[] payload() default {};
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
spring:
|
||||
application:
|
||||
name: reserve-check-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-check-service
|
||||
26
backend/reserve-check-service/src/main/resources/schema.sql
Normal file
26
backend/reserve-check-service/src/main/resources/schema.sql
Normal file
@@ -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 '예약 신청&확인';
|
||||
|
||||
Reference in New Issue
Block a user