refactor: reformat code
This commit is contained in:
@@ -1,29 +1,32 @@
|
|||||||
package org.egovframe.cloud.reservechecksevice.api.reserve;
|
package org.egovframe.cloud.reservechecksevice.api;
|
||||||
|
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
|
import javax.validation.Valid;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.egovframe.cloud.common.dto.RequestDto;
|
import org.egovframe.cloud.reservechecksevice.api.dto.ReserveCancelRequestDto;
|
||||||
import org.egovframe.cloud.reservechecksevice.api.reserve.dto.*;
|
import org.egovframe.cloud.reservechecksevice.api.dto.ReserveListResponseDto;
|
||||||
import org.egovframe.cloud.reservechecksevice.domain.reserve.Category;
|
import org.egovframe.cloud.reservechecksevice.api.dto.ReserveRequestDto;
|
||||||
import org.egovframe.cloud.reservechecksevice.service.reserve.ReserveService;
|
import org.egovframe.cloud.reservechecksevice.api.dto.ReserveResponseDto;
|
||||||
|
import org.egovframe.cloud.reservechecksevice.api.dto.ReserveSaveRequestDto;
|
||||||
|
import org.egovframe.cloud.reservechecksevice.api.dto.ReserveUpdateRequestDto;
|
||||||
|
import org.egovframe.cloud.reservechecksevice.service.ReserveService;
|
||||||
import org.springframework.core.env.Environment;
|
import org.springframework.core.env.Environment;
|
||||||
import org.springframework.data.domain.Page;
|
import org.springframework.data.domain.Page;
|
||||||
import org.springframework.data.domain.PageRequest;
|
import org.springframework.data.domain.PageRequest;
|
||||||
import org.springframework.format.annotation.DateTimeFormat;
|
import org.springframework.format.annotation.DateTimeFormat;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.security.core.Authentication;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
import org.springframework.security.core.context.ReactiveSecurityContextHolder;
|
import org.springframework.web.bind.annotation.PathVariable;
|
||||||
import org.springframework.security.core.context.SecurityContext;
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
import org.springframework.security.core.context.SecurityContextHolder;
|
import org.springframework.web.bind.annotation.PutMapping;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
import reactor.core.publisher.Flux;
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
|
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
import reactor.core.publisher.Mono;
|
import reactor.core.publisher.Mono;
|
||||||
|
|
||||||
import javax.validation.Valid;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* org.egovframe.cloud.reservechecksevice.api.reserve.ReserveApiController
|
* org.egovframe.cloud.reservechecksevice.api.ReserveApiController
|
||||||
* <p>
|
* <p>
|
||||||
* 예약 확인 rest controller class
|
* 예약 확인 rest controller class
|
||||||
*
|
*
|
||||||
@@ -1,14 +1,13 @@
|
|||||||
package org.egovframe.cloud.reservechecksevice.api.reserve.dto;
|
package org.egovframe.cloud.reservechecksevice.api.dto;
|
||||||
|
|
||||||
import javax.validation.constraints.NotBlank;
|
import javax.validation.constraints.NotBlank;
|
||||||
|
|
||||||
import lombok.Builder;
|
import lombok.Builder;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
import lombok.ToString;
|
import lombok.ToString;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* org.egovframe.cloud.reservechecksevice.api.reserve.dto.ReserveCancelRequestDto
|
* org.egovframe.cloud.reservechecksevice.api.dto.ReserveCancelRequestDto
|
||||||
* <p>
|
* <p>
|
||||||
* 예약 취소 요청 dto class
|
* 예약 취소 요청 dto class
|
||||||
*
|
*
|
||||||
@@ -1,15 +1,14 @@
|
|||||||
package org.egovframe.cloud.reservechecksevice.api.reserve.dto;
|
package org.egovframe.cloud.reservechecksevice.api.dto;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
import lombok.Builder;
|
import lombok.Builder;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
import lombok.ToString;
|
import lombok.ToString;
|
||||||
import org.egovframe.cloud.reservechecksevice.domain.reserve.Reserve;
|
import org.egovframe.cloud.reservechecksevice.domain.Reserve;
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* org.egovframe.cloud.reservechecksevice.api.reserve.dto.ReserveListResponseDto
|
* org.egovframe.cloud.reservechecksevice.api.dto.ReserveListResponseDto
|
||||||
* <p>
|
* <p>
|
||||||
* 예약 목록 응답 dto class
|
* 예약 목록 응답 dto class
|
||||||
*
|
*
|
||||||
@@ -1,11 +1,11 @@
|
|||||||
package org.egovframe.cloud.reservechecksevice.api.reserve.dto;
|
package org.egovframe.cloud.reservechecksevice.api.dto;
|
||||||
|
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
import org.egovframe.cloud.common.dto.RequestDto;
|
import org.egovframe.cloud.common.dto.RequestDto;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* org.egovframe.cloud.reservechecksevice.api.reserve.dto.ReserveRequestDto
|
* org.egovframe.cloud.reservechecksevice.api.dto.ReserveRequestDto
|
||||||
* <p>
|
* <p>
|
||||||
* 얘약 목록 요청 dto class
|
* 얘약 목록 요청 dto class
|
||||||
*
|
*
|
||||||
@@ -1,17 +1,15 @@
|
|||||||
package org.egovframe.cloud.reservechecksevice.api.reserve.dto;
|
package org.egovframe.cloud.reservechecksevice.api.dto;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
import lombok.Builder;
|
import lombok.Builder;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
import lombok.ToString;
|
import lombok.ToString;
|
||||||
import org.egovframe.cloud.reservechecksevice.client.dto.ReserveItemRelationResponseDto;
|
import org.egovframe.cloud.reservechecksevice.client.dto.ReserveItemRelationResponseDto;
|
||||||
import org.egovframe.cloud.reservechecksevice.domain.reserve.Reserve;
|
import org.egovframe.cloud.reservechecksevice.domain.Reserve;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
import java.time.LocalDateTime;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* org.egovframe.cloud.reservechecksevice.api.reserve.dto.ReserveResponseDto
|
* org.egovframe.cloud.reservechecksevice.api.dto.ReserveResponseDto
|
||||||
* <p>
|
* <p>
|
||||||
* 예약 확인(신청) 응답 dto class
|
* 예약 확인(신청) 응답 dto class
|
||||||
*
|
*
|
||||||
@@ -1,20 +1,18 @@
|
|||||||
package org.egovframe.cloud.reservechecksevice.api.reserve.dto;
|
package org.egovframe.cloud.reservechecksevice.api.dto;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.UUID;
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
import lombok.Builder;
|
import lombok.Builder;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
import lombok.ToString;
|
import lombok.ToString;
|
||||||
import lombok.With;
|
import org.egovframe.cloud.reservechecksevice.domain.Reserve;
|
||||||
|
|
||||||
import org.egovframe.cloud.reservechecksevice.domain.reserve.Reserve;
|
|
||||||
import org.egovframe.cloud.reservechecksevice.validator.annotation.ReserveSaveValid;
|
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
|
* org.egovframe.cloud.reservechecksevice.api.dto.ReserveSaveRequestDto
|
||||||
* <p>
|
* <p>
|
||||||
* 예약 신청 요청 dto class
|
* 예약 신청 요청 dto class
|
||||||
*
|
*
|
||||||
@@ -77,6 +75,11 @@ public class ReserveSaveRequestDto {
|
|||||||
this.userEmail = userEmail;
|
this.userEmail = userEmail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Reserve createNewReserve() {
|
||||||
|
this.reserveId = String.valueOf(UUID.randomUUID());
|
||||||
|
return toEntity();
|
||||||
|
}
|
||||||
|
|
||||||
public Reserve toEntity() {
|
public Reserve toEntity() {
|
||||||
Reserve reserve = Reserve.builder()
|
Reserve reserve = Reserve.builder()
|
||||||
.reserveId(this.reserveId)
|
.reserveId(this.reserveId)
|
||||||
@@ -1,16 +1,15 @@
|
|||||||
package org.egovframe.cloud.reservechecksevice.api.reserve.dto;
|
package org.egovframe.cloud.reservechecksevice.api.dto;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
import lombok.Builder;
|
import lombok.Builder;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
import lombok.ToString;
|
import lombok.ToString;
|
||||||
import org.egovframe.cloud.reservechecksevice.validator.annotation.ReserveSaveValid;
|
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
|
* org.egovframe.cloud.reservechecksevice.api.dto.ReserveUpdateRequestDto
|
||||||
* <p>
|
* <p>
|
||||||
* 예약 신청 정보 수정 요청 dto class
|
* 예약 신청 정보 수정 요청 dto class
|
||||||
*
|
*
|
||||||
@@ -6,7 +6,6 @@ import org.springframework.web.bind.annotation.GetMapping;
|
|||||||
import org.springframework.web.bind.annotation.PathVariable;
|
import org.springframework.web.bind.annotation.PathVariable;
|
||||||
import org.springframework.web.bind.annotation.PutMapping;
|
import org.springframework.web.bind.annotation.PutMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestBody;
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
|
|
||||||
import reactivefeign.spring.config.ReactiveFeignClient;
|
import reactivefeign.spring.config.ReactiveFeignClient;
|
||||||
import reactor.core.publisher.Mono;
|
import reactor.core.publisher.Mono;
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ package org.egovframe.cloud.reservechecksevice.client;
|
|||||||
import org.egovframe.cloud.reservechecksevice.client.dto.UserResponseDto;
|
import org.egovframe.cloud.reservechecksevice.client.dto.UserResponseDto;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
import org.springframework.web.bind.annotation.PathVariable;
|
import org.springframework.web.bind.annotation.PathVariable;
|
||||||
|
|
||||||
import reactivefeign.spring.config.ReactiveFeignClient;
|
import reactivefeign.spring.config.ReactiveFeignClient;
|
||||||
import reactor.core.publisher.Mono;
|
import reactor.core.publisher.Mono;
|
||||||
|
|
||||||
|
|||||||
@@ -1,16 +1,14 @@
|
|||||||
package org.egovframe.cloud.reservechecksevice.client.dto;
|
package org.egovframe.cloud.reservechecksevice.client.dto;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Builder;
|
import lombok.Builder;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
import lombok.ToString;
|
import lombok.ToString;
|
||||||
|
import org.egovframe.cloud.reservechecksevice.domain.ReserveItem;
|
||||||
import org.egovframe.cloud.reservechecksevice.domain.location.Location;
|
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
|
* org.egovframe.cloud.reservechecksevice.client.dto.ReserveItemRelationResponseDto
|
||||||
|
|||||||
@@ -1,13 +1,12 @@
|
|||||||
package org.egovframe.cloud.reservechecksevice.client.dto;
|
package org.egovframe.cloud.reservechecksevice.client.dto;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
import lombok.Builder;
|
import lombok.Builder;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
import lombok.ToString;
|
import lombok.ToString;
|
||||||
import org.egovframe.cloud.reservechecksevice.domain.reserve.ReserveItem;
|
import org.egovframe.cloud.reservechecksevice.domain.ReserveItem;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
import java.time.LocalDateTime;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* org.egovframe.cloud.reserveitemservice.api.reserveItem.dto.ReserveItemResponseDto
|
* org.egovframe.cloud.reserveitemservice.api.reserveItem.dto.ReserveItemResponseDto
|
||||||
@@ -30,6 +29,8 @@ import java.time.LocalDateTime;
|
|||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
@ToString
|
@ToString
|
||||||
public class ReserveItemResponseDto {
|
public class ReserveItemResponseDto {
|
||||||
|
private static final int MIN_QTY = 0;
|
||||||
|
|
||||||
private Long reserveItemId; // 예약 물품 id
|
private Long reserveItemId; // 예약 물품 id
|
||||||
private String reserveItemName; //예약 물품 명
|
private String reserveItemName; //예약 물품 명
|
||||||
private Long locationId;
|
private Long locationId;
|
||||||
@@ -90,4 +91,16 @@ public class ReserveItemResponseDto {
|
|||||||
this.managerName = reserveItem.getManagerName();
|
this.managerName = reserveItem.getManagerName();
|
||||||
this.managerContact = reserveItem.getManagerContact();
|
this.managerContact = reserveItem.getManagerContact();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isPossibleQty(Integer max, Integer reserveQty) {
|
||||||
|
return (totalQty - max) >= reserveQty;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isPositiveInventory() {
|
||||||
|
return inventoryQty > MIN_QTY;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isPossibleInventoryQty(Integer reserveQty) {
|
||||||
|
return inventoryQty >= reserveQty;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,10 @@
|
|||||||
package org.egovframe.cloud.reservechecksevice.config;
|
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.CircuitBreakerConfig;
|
||||||
import io.github.resilience4j.circuitbreaker.CircuitBreakerRegistry;
|
import io.github.resilience4j.circuitbreaker.CircuitBreakerRegistry;
|
||||||
|
import java.time.Duration;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* org.egovframe.cloud.portalservice.config.Resilience4JConfig
|
* org.egovframe.cloud.portalservice.config.Resilience4JConfig
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
package org.egovframe.cloud.reservechecksevice.domain.reserve;
|
package org.egovframe.cloud.reservechecksevice.domain;
|
||||||
|
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* org.egovframe.cloud.reservechecksevice.domain.reserve.Category
|
* org.egovframe.cloud.reservechecksevice.domain.Category
|
||||||
*
|
*
|
||||||
* 예약 유형 enum class
|
* 예약 유형 enum class
|
||||||
*
|
*
|
||||||
@@ -1,21 +1,23 @@
|
|||||||
package org.egovframe.cloud.reservechecksevice.domain.reserve;
|
package org.egovframe.cloud.reservechecksevice.domain;
|
||||||
|
|
||||||
import lombok.*;
|
import java.time.LocalDateTime;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.Setter;
|
||||||
|
import lombok.ToString;
|
||||||
|
import lombok.With;
|
||||||
|
import org.egovframe.cloud.common.exception.BusinessMessageException;
|
||||||
import org.egovframe.cloud.reactive.domain.BaseEntity;
|
import org.egovframe.cloud.reactive.domain.BaseEntity;
|
||||||
import org.egovframe.cloud.reservechecksevice.api.reserve.dto.ReserveUpdateRequestDto;
|
import org.egovframe.cloud.reservechecksevice.api.dto.ReserveUpdateRequestDto;
|
||||||
import org.egovframe.cloud.reservechecksevice.client.dto.UserResponseDto;
|
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.Id;
|
||||||
import org.springframework.data.annotation.Transient;
|
import org.springframework.data.annotation.Transient;
|
||||||
import org.springframework.data.relational.core.mapping.Column;
|
import org.springframework.data.relational.core.mapping.Column;
|
||||||
import org.springframework.data.relational.core.mapping.Table;
|
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
|
* org.egovframe.cloud.reservechecksevice.domain.Reserve
|
||||||
*
|
*
|
||||||
* 예약 도메인 클래스
|
* 예약 도메인 클래스
|
||||||
*
|
*
|
||||||
@@ -112,6 +114,10 @@ public class Reserve extends BaseEntity {
|
|||||||
this.userEmail = userEmail;
|
this.userEmail = userEmail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isReserveUser(String userId) {
|
||||||
|
return this.userId.equals(userId);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 물품 정보 세팅
|
* 물품 정보 세팅
|
||||||
*
|
*
|
||||||
@@ -203,4 +209,26 @@ public class Reserve extends BaseEntity {
|
|||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isDone() {
|
||||||
|
return ReserveStatus.DONE.isEquals(this.reserveStatusId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Reserve updateStatusCancel(String reason, String errorMessage) {
|
||||||
|
if (isDone()) {
|
||||||
|
throw new BusinessMessageException(errorMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.reserveStatusId = ReserveStatus.CANCEL.getKey();
|
||||||
|
this.reasonCancelContent = reason;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isEducation() {
|
||||||
|
return Category.EDUCATION.isEquals(this.getCategoryId());
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isRequest() {
|
||||||
|
return ReserveStatus.REQUEST.isEquals(this.reserveStatusId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,10 @@
|
|||||||
package org.egovframe.cloud.reservechecksevice.domain.reserve;
|
package org.egovframe.cloud.reservechecksevice.domain;
|
||||||
|
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
|
import javax.validation.constraints.Size;
|
||||||
import lombok.Builder;
|
import lombok.Builder;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
@@ -10,12 +14,6 @@ import org.egovframe.cloud.reservechecksevice.domain.location.Location;
|
|||||||
import org.springframework.data.annotation.Id;
|
import org.springframework.data.annotation.Id;
|
||||||
import org.springframework.data.annotation.Transient;
|
import org.springframework.data.annotation.Transient;
|
||||||
import org.springframework.data.relational.core.mapping.Column;
|
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
|
* org.egovframe.cloud.reserveitemservice.domain.reserveItem.ReserveItem
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
package org.egovframe.cloud.reservechecksevice.domain.reserve;
|
package org.egovframe.cloud.reservechecksevice.domain;
|
||||||
|
|
||||||
import org.springframework.data.r2dbc.repository.R2dbcRepository;
|
import org.springframework.data.r2dbc.repository.R2dbcRepository;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* org.egovframe.cloud.reservechecksevice.domain.reserve.ReserveRepository
|
* org.egovframe.cloud.reservechecksevice.domain.ReserveRepository
|
||||||
*
|
*
|
||||||
* 예약 도메인 Repository interface
|
* 예약 도메인 Repository interface
|
||||||
*
|
*
|
||||||
@@ -1,15 +1,13 @@
|
|||||||
package org.egovframe.cloud.reservechecksevice.domain.reserve;
|
package org.egovframe.cloud.reservechecksevice.domain;
|
||||||
|
|
||||||
import org.egovframe.cloud.common.dto.RequestDto;
|
import java.time.LocalDateTime;
|
||||||
import org.egovframe.cloud.reservechecksevice.api.reserve.dto.ReserveRequestDto;
|
import org.egovframe.cloud.reservechecksevice.api.dto.ReserveRequestDto;
|
||||||
import org.springframework.data.domain.Pageable;
|
import org.springframework.data.domain.Pageable;
|
||||||
import reactor.core.publisher.Flux;
|
import reactor.core.publisher.Flux;
|
||||||
import reactor.core.publisher.Mono;
|
import reactor.core.publisher.Mono;
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* org.egovframe.cloud.reservechecksevice.domain.reserve.ReserveRepositoryCustom
|
* org.egovframe.cloud.reservechecksevice.domain.ReserveRepositoryCustom
|
||||||
*
|
*
|
||||||
* 예약 도메인 custom Repository interface
|
* 예약 도메인 custom Repository interface
|
||||||
*
|
*
|
||||||
@@ -1,14 +1,15 @@
|
|||||||
package org.egovframe.cloud.reservechecksevice.domain.reserve;
|
package org.egovframe.cloud.reservechecksevice.domain;
|
||||||
|
|
||||||
import static org.springframework.data.relational.core.query.Criteria.*;
|
import static org.springframework.data.relational.core.query.Criteria.where;
|
||||||
|
|
||||||
import java.time.LocalDate;
|
import io.github.resilience4j.circuitbreaker.CircuitBreaker;
|
||||||
|
import io.github.resilience4j.circuitbreaker.CircuitBreakerRegistry;
|
||||||
|
import io.github.resilience4j.reactor.circuitbreaker.operator.CircuitBreakerOperator;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.time.LocalTime;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.egovframe.cloud.reservechecksevice.api.reserve.dto.ReserveRequestDto;
|
import org.egovframe.cloud.reservechecksevice.api.dto.ReserveRequestDto;
|
||||||
import org.egovframe.cloud.reservechecksevice.client.ReserveItemServiceClient;
|
import org.egovframe.cloud.reservechecksevice.client.ReserveItemServiceClient;
|
||||||
import org.egovframe.cloud.reservechecksevice.client.UserServiceClient;
|
import org.egovframe.cloud.reservechecksevice.client.UserServiceClient;
|
||||||
import org.egovframe.cloud.reservechecksevice.client.dto.UserResponseDto;
|
import org.egovframe.cloud.reservechecksevice.client.dto.UserResponseDto;
|
||||||
@@ -18,16 +19,11 @@ import org.springframework.data.r2dbc.core.R2dbcEntityTemplate;
|
|||||||
import org.springframework.data.relational.core.query.Criteria;
|
import org.springframework.data.relational.core.query.Criteria;
|
||||||
import org.springframework.data.relational.core.query.Query;
|
import org.springframework.data.relational.core.query.Query;
|
||||||
import org.springframework.util.StringUtils;
|
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.Flux;
|
||||||
import reactor.core.publisher.Mono;
|
import reactor.core.publisher.Mono;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* org.egovframe.cloud.reservechecksevice.domain.reserve.ReserveRepositoryImpl
|
* org.egovframe.cloud.reservechecksevice.domain.ReserveRepositoryImpl
|
||||||
*
|
*
|
||||||
* 예약 도메인 custom repository 구현 클래스
|
* 예약 도메인 custom repository 구현 클래스
|
||||||
*
|
*
|
||||||
@@ -1,10 +1,10 @@
|
|||||||
package org.egovframe.cloud.reservechecksevice.domain.reserve;
|
package org.egovframe.cloud.reservechecksevice.domain;
|
||||||
|
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* org.egovframe.cloud.reservechecksevice.domain.reserve.ReserveStatus
|
* org.egovframe.cloud.reservechecksevice.domain.ReserveStatus
|
||||||
*
|
*
|
||||||
* 예약 상태 enum class
|
* 예약 상태 enum class
|
||||||
*
|
*
|
||||||
@@ -0,0 +1,259 @@
|
|||||||
|
package org.egovframe.cloud.reservechecksevice.domain;
|
||||||
|
|
||||||
|
import io.github.resilience4j.circuitbreaker.CircuitBreakerRegistry;
|
||||||
|
import io.github.resilience4j.reactor.circuitbreaker.operator.CircuitBreakerOperator;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.temporal.ChronoUnit;
|
||||||
|
import java.util.stream.IntStream;
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.egovframe.cloud.common.exception.BusinessMessageException;
|
||||||
|
import org.egovframe.cloud.common.util.MessageUtil;
|
||||||
|
import org.egovframe.cloud.reservechecksevice.client.ReserveItemServiceClient;
|
||||||
|
import org.egovframe.cloud.reservechecksevice.client.dto.ReserveItemResponseDto;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import reactor.core.publisher.Flux;
|
||||||
|
import reactor.core.publisher.Mono;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class ReserveValidator {
|
||||||
|
private static final String CHECK_RESERVE_MEANS = "realtime";
|
||||||
|
private static final String RESERVE_ITEM_CIRCUIT_BREAKER_NAME = "reserve-item";
|
||||||
|
|
||||||
|
@Resource(
|
||||||
|
name = "messageUtil"
|
||||||
|
)
|
||||||
|
protected MessageUtil messageUtil;
|
||||||
|
|
||||||
|
private final ReserveRepository reserveRepository;
|
||||||
|
private final ReserveItemServiceClient reserveItemServiceClient;
|
||||||
|
private final CircuitBreakerRegistry circuitBreakerRegistry;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 공간 예약 시 예약 날짜에 다른 예약이 있는지 체크
|
||||||
|
*
|
||||||
|
* @param reserveItem
|
||||||
|
* @param reserve
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public 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
|
||||||
|
*/
|
||||||
|
public 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 -> Mono.just((reserveItem.isPossibleQty(max, reserve.getReserveQty()))))
|
||||||
|
.flatMap(isValid -> {
|
||||||
|
if (isValid) {
|
||||||
|
return Mono.just(reserve);
|
||||||
|
}
|
||||||
|
//해당 날짜에 예약할 수 있는 재고수량이 없습니다.
|
||||||
|
return Mono.error(new BusinessMessageException(getMessage("valid.reserve_count")));
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 교육 예약 시 재고 체크
|
||||||
|
*
|
||||||
|
* @param reserveItem
|
||||||
|
* @param reserve
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public 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.isPositiveInventory()) {
|
||||||
|
//"예약이 마감되었습니다."
|
||||||
|
return Mono.error(new BusinessMessageException(getMessage("valid.reserve_close")));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (reserveItemResponseDto.isPossibleInventoryQty(reserve.getReserveQty())) {
|
||||||
|
//예약가능한 인원이 부족합니다. (남은 인원 : {0})
|
||||||
|
return Mono.error(new BusinessMessageException(getMessage("valid.reserve_number_of_people", new Object[]{reserveItemResponseDto.getInventoryQty()})));
|
||||||
|
}
|
||||||
|
return Mono.just(reserve);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 예약물품에 대해 날짜별 예약된 수량 max 조회
|
||||||
|
*
|
||||||
|
* @param reserveItemId
|
||||||
|
* @param startDate
|
||||||
|
* @param endDate
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 예약 물품 재고 및 예약 일자 체크
|
||||||
|
*
|
||||||
|
* @param reserve
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public 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 checkSpace(reserveItemResponseDto, reserve);
|
||||||
|
}
|
||||||
|
if (Category.EQUIPMENT.isEquals(reserveItemResponseDto.getCategoryId())) {
|
||||||
|
return checkEquipment(reserveItemResponseDto, reserve);
|
||||||
|
}
|
||||||
|
if (Category.EDUCATION.isEquals(reserveItemResponseDto.getCategoryId())) {
|
||||||
|
return 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 예약물품에 대해 날짜별 예약된 수량 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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);
|
||||||
|
|
||||||
|
if (between == 0) {
|
||||||
|
return reserveFlux.map(reserve -> {
|
||||||
|
if (startDate.isAfter(reserve.getReserveStartDate())
|
||||||
|
|| startDate.isBefore(reserve.getReserveEndDate())
|
||||||
|
|| startDate.isEqual(reserve.getReserveStartDate()) || startDate.isEqual(reserve.getReserveEndDate())) {
|
||||||
|
return reserve.getReserveQty();
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}).reduce(0, (x1, x2) -> x1 + x2);
|
||||||
|
}
|
||||||
|
|
||||||
|
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())
|
||||||
|
|| localDateTime.isEqual(findReserve.getReserveStartDate()) || localDateTime.isEqual(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);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getMessage(String code) {
|
||||||
|
return this.messageUtil.getMessage(code);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getMessage(String code, Object[] args) {
|
||||||
|
return this.messageUtil.getMessage(code, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,12 +1,13 @@
|
|||||||
package org.egovframe.cloud.reservechecksevice.domain.location;
|
package org.egovframe.cloud.reservechecksevice.domain.location;
|
||||||
|
|
||||||
import lombok.*;
|
import javax.validation.constraints.Size;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.ToString;
|
||||||
import org.egovframe.cloud.reactive.domain.BaseEntity;
|
import org.egovframe.cloud.reactive.domain.BaseEntity;
|
||||||
import org.springframework.data.annotation.Id;
|
import org.springframework.data.annotation.Id;
|
||||||
import org.springframework.data.relational.core.mapping.Column;
|
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
|
* org.egovframe.cloud.reserveitemservice.domain.location.Location
|
||||||
|
|||||||
@@ -0,0 +1,411 @@
|
|||||||
|
package org.egovframe.cloud.reservechecksevice.service;
|
||||||
|
|
||||||
|
import io.github.resilience4j.circuitbreaker.CircuitBreakerRegistry;
|
||||||
|
import io.github.resilience4j.reactor.circuitbreaker.operator.CircuitBreakerOperator;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
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.dto.ReserveCancelRequestDto;
|
||||||
|
import org.egovframe.cloud.reservechecksevice.api.dto.ReserveListResponseDto;
|
||||||
|
import org.egovframe.cloud.reservechecksevice.api.dto.ReserveRequestDto;
|
||||||
|
import org.egovframe.cloud.reservechecksevice.api.dto.ReserveResponseDto;
|
||||||
|
import org.egovframe.cloud.reservechecksevice.api.dto.ReserveSaveRequestDto;
|
||||||
|
import org.egovframe.cloud.reservechecksevice.api.dto.ReserveUpdateRequestDto;
|
||||||
|
import org.egovframe.cloud.reservechecksevice.client.ReserveItemServiceClient;
|
||||||
|
import org.egovframe.cloud.reservechecksevice.domain.Reserve;
|
||||||
|
import org.egovframe.cloud.reservechecksevice.domain.ReserveRepository;
|
||||||
|
import org.egovframe.cloud.reservechecksevice.domain.ReserveStatus;
|
||||||
|
import org.egovframe.cloud.reservechecksevice.domain.ReserveValidator;
|
||||||
|
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 reactor.core.publisher.Flux;
|
||||||
|
import reactor.core.publisher.Mono;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* org.egovframe.cloud.reservechecksevice.service.ReserveService
|
||||||
|
* <p>
|
||||||
|
* 예약 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 final ReserveRepository reserveRepository;
|
||||||
|
private final ReserveItemServiceClient reserveItemServiceClient;
|
||||||
|
private final CircuitBreakerRegistry circuitBreakerRegistry;
|
||||||
|
private final StreamBridge streamBridge;
|
||||||
|
private final ReserveValidator validator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 목록 조회
|
||||||
|
*
|
||||||
|
* @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().isReserveUser(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 ->
|
||||||
|
reserve.updateStatusCancel(cancelRequestDto.getReasonCancelContent(), getMessage("valid.cant_cancel_because_done")))
|
||||||
|
.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(Mono::error)
|
||||||
|
.flatMap(this::checkApprove)
|
||||||
|
.onErrorResume(Mono::error)
|
||||||
|
.flatMap(reserveRepository::save).then();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 예약 정보 수정
|
||||||
|
*
|
||||||
|
* @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 saveRequestDto
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public Mono<ReserveResponseDto> create(ReserveSaveRequestDto saveRequestDto) {
|
||||||
|
return Mono.just(saveRequestDto)
|
||||||
|
.map(ReserveSaveRequestDto::createNewReserve)
|
||||||
|
.zipWith(getUserId())
|
||||||
|
.flatMap(tuple -> Mono.just(tuple.getT1().setCreatedInfo(LocalDateTime.now(), tuple.getT2())))
|
||||||
|
.flatMap(validator::checkReserveItems)
|
||||||
|
.onErrorResume(Mono::error)
|
||||||
|
.flatMap(this::updateInventory)
|
||||||
|
.onErrorResume(Mono::error)
|
||||||
|
.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);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 예약 물품별 기간안에 있는 예약된 수량 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(validator.getMaxByReserveDate(reserveItemId, startDate, endDate))
|
||||||
|
.flatMap(tuple -> Mono.just(tuple.getT1().getTotalQty() - tuple.getT2()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 승인 전 validate check 및 교육인 경우 재고 업데이트
|
||||||
|
*
|
||||||
|
* @param reserveId
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private Mono<Reserve> checkApprove(String reserveId) {
|
||||||
|
return findById(reserveId)
|
||||||
|
.flatMap(validator::checkReserveItems)
|
||||||
|
.onErrorResume(Mono::error)
|
||||||
|
.map(reserve -> reserve.updateStatus(ReserveStatus.APPROVE.getKey()))
|
||||||
|
.flatMap(this::updateInventory);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 사용자 예약 수정
|
||||||
|
*
|
||||||
|
* @param reserveId
|
||||||
|
* @param updateRequestDto
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private Mono<Reserve> updateReserveForUser(String reserveId,
|
||||||
|
ReserveUpdateRequestDto updateRequestDto) {
|
||||||
|
return findById(reserveId)
|
||||||
|
.zipWith(getUserId())
|
||||||
|
.map(tuple -> {
|
||||||
|
if (!tuple.getT1().isReserveUser(tuple.getT2())) {
|
||||||
|
//"해당 예약은 수정할 수 없습니다."
|
||||||
|
throw new BusinessMessageException(getMessage("valid.reserve_not_update"));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!tuple.getT1().isRequest()) {
|
||||||
|
//예약 신청 상태인 경우에만 수정 가능합니다.
|
||||||
|
throw new BusinessMessageException(getMessage("valid.reserve_not_update_status"));
|
||||||
|
}
|
||||||
|
|
||||||
|
return tuple.getT1().update(updateRequestDto);
|
||||||
|
})
|
||||||
|
.flatMap(validator::checkReserveItems)
|
||||||
|
.onErrorResume(Mono::error)
|
||||||
|
.flatMap(this::updateInventory)
|
||||||
|
.onErrorResume(Mono::error)
|
||||||
|
.flatMap(reserveRepository::save);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 관리자 예약 수정
|
||||||
|
*
|
||||||
|
* @param reserveId
|
||||||
|
* @param updateRequestDto
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private Mono<Reserve> updateReserve(String reserveId,
|
||||||
|
ReserveUpdateRequestDto updateRequestDto) {
|
||||||
|
return findById(reserveId)
|
||||||
|
.map(reserve -> {
|
||||||
|
if (!reserve.isRequest()) {
|
||||||
|
//예약 신청 상태인 경우에만 수정 가능합니다.
|
||||||
|
throw new BusinessMessageException(
|
||||||
|
getMessage("valid.reserve_not_update_status"));
|
||||||
|
}
|
||||||
|
return reserve.update(updateRequestDto);
|
||||||
|
})
|
||||||
|
.flatMap(validator::checkReserveItems)
|
||||||
|
.onErrorResume(Mono::error)
|
||||||
|
.flatMap(this::updateInventory)
|
||||||
|
.onErrorResume(Mono::error)
|
||||||
|
.flatMap(reserveRepository::save);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 예약 정보 저장 시 재고 변경
|
||||||
|
*
|
||||||
|
* @param reserve
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private Mono<Reserve> updateInventory(Reserve reserve) {
|
||||||
|
return Mono.just(reserve)
|
||||||
|
.flatMap(it -> {
|
||||||
|
if (it.isEducation()) {
|
||||||
|
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 Mono.just(it);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 한건 정보 조회 entity return
|
||||||
|
*
|
||||||
|
* @param reserveId
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private Mono<Reserve> findById(String reserveId) {
|
||||||
|
return reserveRepository.findById(reserveId)
|
||||||
|
.switchIfEmpty(monoResponseStatusEntityNotFoundException(reserveId));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,640 +0,0 @@
|
|||||||
package org.egovframe.cloud.reservechecksevice.service.reserve;
|
|
||||||
|
|
||||||
import java.time.LocalDate;
|
|
||||||
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")));
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 예약 물품별 기간안에 있는 예약된 수량 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))
|
|
||||||
.log("countinventory")
|
|
||||||
.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);
|
|
||||||
|
|
||||||
if (between == 0) {
|
|
||||||
return reserveFlux.map(reserve -> {
|
|
||||||
if (startDate.isAfter(reserve.getReserveStartDate())
|
|
||||||
|| startDate.isBefore(reserve.getReserveEndDate())
|
|
||||||
|| startDate.isEqual(reserve.getReserveStartDate()) || startDate.isEqual(reserve.getReserveEndDate())) {
|
|
||||||
return reserve.getReserveQty();
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}).reduce(0, (x1, x2) -> x1 + x2);
|
|
||||||
}
|
|
||||||
|
|
||||||
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())
|
|
||||||
|| localDateTime.isEqual(findReserve.getReserveStartDate()) || localDateTime.isEqual(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);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -2,22 +2,19 @@ package org.egovframe.cloud.reservechecksevice.validator;
|
|||||||
|
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import javax.validation.ConstraintValidator;
|
import javax.validation.ConstraintValidator;
|
||||||
import javax.validation.ConstraintValidatorContext;
|
import javax.validation.ConstraintValidatorContext;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.SneakyThrows;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.egovframe.cloud.common.util.MessageUtil;
|
import org.egovframe.cloud.common.util.MessageUtil;
|
||||||
import org.egovframe.cloud.reservechecksevice.validator.annotation.ReserveSaveValid;
|
import org.egovframe.cloud.reservechecksevice.validator.annotation.ReserveSaveValid;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import lombok.SneakyThrows;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* org.egovframe.cloud.reservechecksevice.validator.ReserveSaveValidator
|
* org.egovframe.cloud.reservechecksevice.validator.ReserveSaveValidator
|
||||||
*
|
* <p>
|
||||||
* 예약 신청 시 validation check를 하기 위한 custom validator
|
* 예약 신청 시 validation check를 하기 위한 custom validator
|
||||||
*
|
*
|
||||||
* @author 표준프레임워크센터 shinmj
|
* @author 표준프레임워크센터 shinmj
|
||||||
@@ -42,6 +39,7 @@ public class ReserveSaveValidator implements ConstraintValidator<ReserveSaveVali
|
|||||||
protected MessageUtil messageUtil;
|
protected MessageUtil messageUtil;
|
||||||
|
|
||||||
private String message;
|
private String message;
|
||||||
|
private boolean fieldValid;
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -59,24 +57,28 @@ public class ReserveSaveValidator implements ConstraintValidator<ReserveSaveVali
|
|||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
@Override
|
@Override
|
||||||
public boolean isValid(Object value, ConstraintValidatorContext context) {
|
public boolean isValid(Object value, ConstraintValidatorContext context) {
|
||||||
boolean fieldValid = true;
|
fieldValid = true;
|
||||||
|
|
||||||
String categoryId = String.valueOf(getFieldValue(value, "categoryId"));
|
String categoryId = String.valueOf(getFieldValue(value, "categoryId"));
|
||||||
if ("education".equals(categoryId)) {
|
if ("education".equals(categoryId)) {
|
||||||
//교육인 경우
|
//교육인 경우
|
||||||
//신청인원
|
//신청인원
|
||||||
fieldValid = checkReserveQty(value, context);
|
return checkReserveQty(value, context);
|
||||||
|
}
|
||||||
|
|
||||||
}else if ("equipment".equals(categoryId)) {
|
if ("equipment".equals(categoryId)) {
|
||||||
//장비인 경우
|
//장비인 경우
|
||||||
//신청일자(기간), 신청수량
|
//신청일자(기간), 신청수량
|
||||||
fieldValid = checkReserveDate(value, context);
|
fieldValid = checkReserveDate(value, context);
|
||||||
fieldValid = checkReserveQty(value, context);
|
fieldValid = checkReserveQty(value, context);
|
||||||
|
|
||||||
}else if ("place".equals(categoryId)) {
|
return fieldValid;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ("place".equals(categoryId)) {
|
||||||
//공간인 경우
|
//공간인 경우
|
||||||
//신청일자(기간)
|
//신청일자(기간)
|
||||||
fieldValid = checkReserveDate(value, context);
|
return checkReserveDate(value, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
return fieldValid;
|
return fieldValid;
|
||||||
@@ -94,12 +96,14 @@ public class ReserveSaveValidator implements ConstraintValidator<ReserveSaveVali
|
|||||||
if (isNull(value, "reserveQty")) {
|
if (isNull(value, "reserveQty")) {
|
||||||
context.disableDefaultConstraintViolation();
|
context.disableDefaultConstraintViolation();
|
||||||
//예약 수량 값은 필수 입니다.
|
//예약 수량 값은 필수 입니다.
|
||||||
context.buildConstraintViolationWithTemplate(messageUtil.getMessage("reserve")+" "+messageUtil.getMessage("reserve.count") + messageUtil.getMessage("valid.required"))
|
context.buildConstraintViolationWithTemplate(
|
||||||
|
messageUtil.getMessage("reserve") + " " + messageUtil.getMessage("reserve.count")
|
||||||
|
+ messageUtil.getMessage("valid.required"))
|
||||||
.addPropertyNode("reserveQty")
|
.addPropertyNode("reserveQty")
|
||||||
.addConstraintViolation();
|
.addConstraintViolation();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return fieldValid;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -115,31 +119,41 @@ public class ReserveSaveValidator implements ConstraintValidator<ReserveSaveVali
|
|||||||
if (isNull(value, "reserveStartDate")) {
|
if (isNull(value, "reserveStartDate")) {
|
||||||
context.disableDefaultConstraintViolation();
|
context.disableDefaultConstraintViolation();
|
||||||
// 예약 신청 시작일 값은 필수 입니다.
|
// 예약 신청 시작일 값은 필수 입니다.
|
||||||
context.buildConstraintViolationWithTemplate(messageUtil.getMessage("reserve_item.request")+" "+messageUtil.getMessage("common.start_datetime") + messageUtil.getMessage("valid.required"))
|
context.buildConstraintViolationWithTemplate(
|
||||||
|
messageUtil.getMessage("reserve_item.request") + " " + messageUtil
|
||||||
|
.getMessage("common.start_datetime") + messageUtil.getMessage("valid.required"))
|
||||||
.addPropertyNode("reserveStartDate")
|
.addPropertyNode("reserveStartDate")
|
||||||
.addConstraintViolation();
|
.addConstraintViolation();
|
||||||
return false;
|
return false;
|
||||||
} else if (isNull(value, "reserveEndDate")) {
|
}
|
||||||
|
|
||||||
|
if (isNull(value, "reserveEndDate")) {
|
||||||
context.disableDefaultConstraintViolation();
|
context.disableDefaultConstraintViolation();
|
||||||
// 예약 신청 종료일 값은 필수 입니다.
|
// 예약 신청 종료일 값은 필수 입니다.
|
||||||
context.buildConstraintViolationWithTemplate(messageUtil.getMessage("reserve_item.request")+" "+messageUtil.getMessage("common.end_datetime") + messageUtil.getMessage("valid.required"))
|
context.buildConstraintViolationWithTemplate(
|
||||||
|
messageUtil.getMessage("reserve_item.request") + " " + messageUtil
|
||||||
|
.getMessage("common.end_datetime") + messageUtil.getMessage("valid.required"))
|
||||||
.addPropertyNode("reserveEndDate")
|
.addPropertyNode("reserveEndDate")
|
||||||
.addConstraintViolation();
|
.addConstraintViolation();
|
||||||
return false;
|
return false;
|
||||||
}else {
|
}
|
||||||
|
|
||||||
// 예약 시작일, 종료일 체크
|
// 예약 시작일, 종료일 체크
|
||||||
LocalDateTime reserveStartDate = (LocalDateTime) getFieldValue(value, "reserveStartDate");
|
LocalDateTime reserveStartDate = (LocalDateTime) getFieldValue(value, "reserveStartDate");
|
||||||
LocalDateTime reserveEndDate = (LocalDateTime) getFieldValue(value, "reserveEndDate");
|
LocalDateTime reserveEndDate = (LocalDateTime) getFieldValue(value, "reserveEndDate");
|
||||||
if (reserveStartDate.isAfter(reserveEndDate)) {
|
if (reserveStartDate.isAfter(reserveEndDate)) {
|
||||||
context.disableDefaultConstraintViolation();
|
context.disableDefaultConstraintViolation();
|
||||||
//시작일, 종료일, {0}이 {1}보다 늦습니다.
|
//시작일, 종료일, {0}이 {1}보다 늦습니다.
|
||||||
context.buildConstraintViolationWithTemplate(messageUtil.getMessage("valid.to_be_slow.format", new Object[]{messageUtil.getMessage("common.start_date"), messageUtil.getMessage("common.end_date")}))
|
context.buildConstraintViolationWithTemplate(messageUtil
|
||||||
|
.getMessage("valid.to_be_slow.format",
|
||||||
|
new Object[]{messageUtil.getMessage("common.start_date"),
|
||||||
|
messageUtil.getMessage("common.end_date")}))
|
||||||
.addPropertyNode("reserveStartDate")
|
.addPropertyNode("reserveStartDate")
|
||||||
.addConstraintViolation();
|
.addConstraintViolation();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return true;
|
return fieldValid;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -151,7 +165,8 @@ public class ReserveSaveValidator implements ConstraintValidator<ReserveSaveVali
|
|||||||
* @throws NoSuchFieldException
|
* @throws NoSuchFieldException
|
||||||
* @throws IllegalAccessException
|
* @throws IllegalAccessException
|
||||||
*/
|
*/
|
||||||
private Object getFieldValue(Object object, String fieldName) throws NoSuchFieldException, IllegalAccessException {
|
private Object getFieldValue(Object object, String fieldName)
|
||||||
|
throws NoSuchFieldException, IllegalAccessException {
|
||||||
Class<?> clazz = object.getClass();
|
Class<?> clazz = object.getClass();
|
||||||
Field field = clazz.getDeclaredField(fieldName);
|
Field field = clazz.getDeclaredField(fieldName);
|
||||||
field.setAccessible(true);
|
field.setAccessible(true);
|
||||||
@@ -167,10 +182,12 @@ public class ReserveSaveValidator implements ConstraintValidator<ReserveSaveVali
|
|||||||
* @throws NoSuchFieldException
|
* @throws NoSuchFieldException
|
||||||
* @throws IllegalAccessException
|
* @throws IllegalAccessException
|
||||||
*/
|
*/
|
||||||
private boolean isNull(Object object, String fieldName) throws NoSuchFieldException, IllegalAccessException {
|
private boolean isNull(Object object, String fieldName)
|
||||||
|
throws NoSuchFieldException, IllegalAccessException {
|
||||||
Class<?> clazz = object.getClass();
|
Class<?> clazz = object.getClass();
|
||||||
Field field = clazz.getDeclaredField(fieldName);
|
Field field = clazz.getDeclaredField(fieldName);
|
||||||
field.setAccessible(true);
|
field.setAccessible(true);
|
||||||
return field.get(object) == null || !StringUtils.hasLength(String.valueOf(field.get(object)));
|
return field.get(object) == null || !StringUtils
|
||||||
|
.hasLength(String.valueOf(field.get(object)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,27 +1,26 @@
|
|||||||
package org.egovframe.cloud.reservechecksevice.api;
|
package org.egovframe.cloud.reservechecksevice.api;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.*;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
import org.egovframe.cloud.common.domain.Role;
|
import org.egovframe.cloud.common.domain.Role;
|
||||||
import org.egovframe.cloud.common.exception.dto.ErrorCode;
|
import org.egovframe.cloud.common.exception.dto.ErrorCode;
|
||||||
import org.egovframe.cloud.common.exception.dto.ErrorResponse;
|
import org.egovframe.cloud.common.exception.dto.ErrorResponse;
|
||||||
import org.egovframe.cloud.reservechecksevice.api.reserve.dto.ReserveCancelRequestDto;
|
import org.egovframe.cloud.reservechecksevice.api.dto.ReserveCancelRequestDto;
|
||||||
import org.egovframe.cloud.reservechecksevice.api.reserve.dto.ReserveListResponseDto;
|
import org.egovframe.cloud.reservechecksevice.api.dto.ReserveListResponseDto;
|
||||||
import org.egovframe.cloud.reservechecksevice.api.reserve.dto.ReserveSaveRequestDto;
|
import org.egovframe.cloud.reservechecksevice.api.dto.ReserveSaveRequestDto;
|
||||||
import org.egovframe.cloud.reservechecksevice.api.reserve.dto.ReserveUpdateRequestDto;
|
import org.egovframe.cloud.reservechecksevice.api.dto.ReserveUpdateRequestDto;
|
||||||
import org.egovframe.cloud.reservechecksevice.client.ReserveItemServiceClient;
|
import org.egovframe.cloud.reservechecksevice.client.ReserveItemServiceClient;
|
||||||
import org.egovframe.cloud.reservechecksevice.client.UserServiceClient;
|
import org.egovframe.cloud.reservechecksevice.client.UserServiceClient;
|
||||||
import org.egovframe.cloud.reservechecksevice.client.dto.ReserveItemRelationResponseDto;
|
import org.egovframe.cloud.reservechecksevice.client.dto.ReserveItemRelationResponseDto;
|
||||||
import org.egovframe.cloud.reservechecksevice.client.dto.ReserveItemResponseDto;
|
import org.egovframe.cloud.reservechecksevice.client.dto.ReserveItemResponseDto;
|
||||||
import org.egovframe.cloud.reservechecksevice.client.dto.UserResponseDto;
|
import org.egovframe.cloud.reservechecksevice.client.dto.UserResponseDto;
|
||||||
|
import org.egovframe.cloud.reservechecksevice.domain.Reserve;
|
||||||
|
import org.egovframe.cloud.reservechecksevice.domain.ReserveItem;
|
||||||
|
import org.egovframe.cloud.reservechecksevice.domain.ReserveRepository;
|
||||||
|
import org.egovframe.cloud.reservechecksevice.domain.ReserveStatus;
|
||||||
import org.egovframe.cloud.reservechecksevice.domain.location.Location;
|
import org.egovframe.cloud.reservechecksevice.domain.location.Location;
|
||||||
import org.egovframe.cloud.reservechecksevice.domain.reserve.Reserve;
|
|
||||||
import org.egovframe.cloud.reservechecksevice.domain.reserve.ReserveItem;
|
|
||||||
import org.egovframe.cloud.reservechecksevice.domain.reserve.ReserveRepository;
|
|
||||||
import org.egovframe.cloud.reservechecksevice.domain.reserve.ReserveStatus;
|
|
||||||
import org.egovframe.cloud.reservechecksevice.util.RestResponsePage;
|
import org.egovframe.cloud.reservechecksevice.util.RestResponsePage;
|
||||||
import org.egovframe.cloud.reservechecksevice.util.WithCustomMockUser;
|
import org.egovframe.cloud.reservechecksevice.util.WithCustomMockUser;
|
||||||
import org.junit.jupiter.api.AfterEach;
|
import org.junit.jupiter.api.AfterEach;
|
||||||
@@ -34,11 +33,9 @@ import org.springframework.boot.context.properties.EnableConfigurationProperties
|
|||||||
import org.springframework.boot.test.context.SpringBootTest;
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
import org.springframework.boot.test.mock.mockito.MockBean;
|
import org.springframework.boot.test.mock.mockito.MockBean;
|
||||||
import org.springframework.core.ParameterizedTypeReference;
|
import org.springframework.core.ParameterizedTypeReference;
|
||||||
import org.springframework.data.r2dbc.core.R2dbcEntityTemplate;
|
|
||||||
import org.springframework.test.context.ActiveProfiles;
|
import org.springframework.test.context.ActiveProfiles;
|
||||||
import org.springframework.test.context.TestPropertySource;
|
import org.springframework.test.context.TestPropertySource;
|
||||||
import org.springframework.test.web.reactive.server.WebTestClient;
|
import org.springframework.test.web.reactive.server.WebTestClient;
|
||||||
|
|
||||||
import reactor.core.publisher.Mono;
|
import reactor.core.publisher.Mono;
|
||||||
|
|
||||||
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
|
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
|
||||||
@@ -59,8 +56,6 @@ public class ReserveApiControllerTest {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private WebTestClient webTestClient;
|
private WebTestClient webTestClient;
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private R2dbcEntityTemplate entityTemplate;
|
|
||||||
|
|
||||||
private static final String API_URL = "/api/v1/reserves";
|
private static final String API_URL = "/api/v1/reserves";
|
||||||
|
|
||||||
@@ -118,7 +113,7 @@ public class ReserveApiControllerTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void 예약신청관리_목록_조회_성공() throws Exception {
|
public void 예약신청관리_목록_조회_성공() {
|
||||||
//given
|
//given
|
||||||
BDDMockito.when(userServiceClient.findByUserId(ArgumentMatchers.anyString()))
|
BDDMockito.when(userServiceClient.findByUserId(ArgumentMatchers.anyString()))
|
||||||
.thenReturn(Mono.just(user));
|
.thenReturn(Mono.just(user));
|
||||||
@@ -146,7 +141,7 @@ public class ReserveApiControllerTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
@WithCustomMockUser(userId = "admin", role = Role.ADMIN)
|
@WithCustomMockUser(userId = "admin", role = Role.ADMIN)
|
||||||
public void 관리자_취소_성공() throws Exception {
|
public void 관리자_취소_성공() {
|
||||||
BDDMockito.when(reserveItemServiceClient.updateInventory(ArgumentMatchers.anyLong(), ArgumentMatchers.anyInt()))
|
BDDMockito.when(reserveItemServiceClient.updateInventory(ArgumentMatchers.anyLong(), ArgumentMatchers.anyInt()))
|
||||||
.thenReturn(Mono.just(true));
|
.thenReturn(Mono.just(true));
|
||||||
|
|
||||||
@@ -189,7 +184,7 @@ public class ReserveApiControllerTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
@WithCustomMockUser(userId = "test", role = Role.USER)
|
@WithCustomMockUser(userId = "test", role = Role.USER)
|
||||||
public void 다른사용자_예약_취소_실패() throws Exception {
|
public void 다른사용자_예약_취소_실패() {
|
||||||
BDDMockito.when(reserveItemServiceClient.updateInventory(ArgumentMatchers.anyLong(), ArgumentMatchers.anyInt()))
|
BDDMockito.when(reserveItemServiceClient.updateInventory(ArgumentMatchers.anyLong(), ArgumentMatchers.anyInt()))
|
||||||
.thenReturn(Mono.just(true));
|
.thenReturn(Mono.just(true));
|
||||||
Reserve saved = reserveRepository.insert(reserve).block();
|
Reserve saved = reserveRepository.insert(reserve).block();
|
||||||
@@ -209,7 +204,7 @@ public class ReserveApiControllerTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
@WithCustomMockUser(userId = "user", role = Role.USER)
|
@WithCustomMockUser(userId = "user", role = Role.USER)
|
||||||
public void 예약상태_완료_취소_실패() throws Exception {
|
public void 예약상태_완료_취소_실패() {
|
||||||
Reserve done = reserve.updateStatus(ReserveStatus.DONE.getKey());
|
Reserve done = reserve.updateStatus(ReserveStatus.DONE.getKey());
|
||||||
Reserve saved = reserveRepository.insert(done).block();
|
Reserve saved = reserveRepository.insert(done).block();
|
||||||
assertNotNull(saved);
|
assertNotNull(saved);
|
||||||
@@ -231,7 +226,7 @@ public class ReserveApiControllerTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
@WithCustomMockUser(userId = "user", role = Role.USER)
|
@WithCustomMockUser(userId = "user", role = Role.USER)
|
||||||
public void 관리자가_아닌_경우_승인_실패() throws Exception {
|
public void 관리자가_아닌_경우_승인_실패() {
|
||||||
Reserve saved = reserveRepository.insert(reserve).block();
|
Reserve saved = reserveRepository.insert(reserve).block();
|
||||||
assertNotNull(saved);
|
assertNotNull(saved);
|
||||||
|
|
||||||
@@ -252,7 +247,7 @@ public class ReserveApiControllerTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
@WithCustomMockUser(userId = "admin", role = Role.ADMIN)
|
@WithCustomMockUser(userId = "admin", role = Role.ADMIN)
|
||||||
public void 예약승인_성공() throws Exception {
|
public void 예약승인_성공() {
|
||||||
|
|
||||||
Reserve saved = reserveRepository.insert(reserve).block();
|
Reserve saved = reserveRepository.insert(reserve).block();
|
||||||
assertNotNull(saved);
|
assertNotNull(saved);
|
||||||
@@ -274,7 +269,7 @@ public class ReserveApiControllerTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
@WithCustomMockUser(userId = "admin", role = Role.ADMIN)
|
@WithCustomMockUser(userId = "admin", role = Role.ADMIN)
|
||||||
public void 예약승인_실패_재고부족() throws Exception {
|
public void 예약승인_실패_재고부족() {
|
||||||
ReserveItem failReserveItem = ReserveItem.builder()
|
ReserveItem failReserveItem = ReserveItem.builder()
|
||||||
.reserveItemId(1L)
|
.reserveItemId(1L)
|
||||||
.reserveItemName("test")
|
.reserveItemName("test")
|
||||||
@@ -313,7 +308,7 @@ public class ReserveApiControllerTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
@WithCustomMockUser(userId = "admin", role = Role.ADMIN)
|
@WithCustomMockUser(userId = "admin", role = Role.ADMIN)
|
||||||
public void 관리자_예약정보_수정_성공() throws Exception {
|
public void 관리자_예약정보_수정_성공() {
|
||||||
Reserve saved = reserveRepository.insert(reserve).block();
|
Reserve saved = reserveRepository.insert(reserve).block();
|
||||||
assertNotNull(saved);
|
assertNotNull(saved);
|
||||||
|
|
||||||
@@ -351,7 +346,7 @@ public class ReserveApiControllerTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
@WithCustomMockUser(userId = "test", role = Role.USER)
|
@WithCustomMockUser(userId = "test", role = Role.USER)
|
||||||
public void 다른사용자_예약정보_수정_실패() throws Exception {
|
public void 다른사용자_예약정보_수정_실패() {
|
||||||
Reserve saved = reserveRepository.insert(reserve).block();
|
Reserve saved = reserveRepository.insert(reserve).block();
|
||||||
assertNotNull(saved);
|
assertNotNull(saved);
|
||||||
|
|
||||||
@@ -387,7 +382,7 @@ public class ReserveApiControllerTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
@WithCustomMockUser(userId = "user", role = Role.USER)
|
@WithCustomMockUser(userId = "user", role = Role.USER)
|
||||||
public void 사용자_예약정보_수정_성공() throws Exception {
|
public void 사용자_예약정보_수정_성공() {
|
||||||
Reserve saved = reserveRepository.insert(reserve).block();
|
Reserve saved = reserveRepository.insert(reserve).block();
|
||||||
assertNotNull(saved);
|
assertNotNull(saved);
|
||||||
|
|
||||||
@@ -426,7 +421,7 @@ public class ReserveApiControllerTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
@WithCustomMockUser(userId = "user", role = Role.USER)
|
@WithCustomMockUser(userId = "user", role = Role.USER)
|
||||||
public void 사용자_상태승인인예약정보_수정_실패() throws Exception {
|
public void 사용자_상태승인인예약정보_수정_실패() {
|
||||||
Reserve failedReserve = reserve.withReserveStatusId(ReserveStatus.APPROVE.getKey());
|
Reserve failedReserve = reserve.withReserveStatusId(ReserveStatus.APPROVE.getKey());
|
||||||
Reserve saved = reserveRepository.insert(failedReserve).block();
|
Reserve saved = reserveRepository.insert(failedReserve).block();
|
||||||
assertNotNull(saved);
|
assertNotNull(saved);
|
||||||
@@ -463,7 +458,7 @@ public class ReserveApiControllerTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void 관리자_예약_성공() throws Exception {
|
public void 관리자_예약_성공() {
|
||||||
BDDMockito.when(reserveItemServiceClient.findById(ArgumentMatchers.anyLong()))
|
BDDMockito.when(reserveItemServiceClient.findById(ArgumentMatchers.anyLong()))
|
||||||
.thenReturn(Mono.just(ReserveItemResponseDto.builder().reserveItem(reserveItem).build()));
|
.thenReturn(Mono.just(ReserveItemResponseDto.builder().reserveItem(reserveItem).build()));
|
||||||
BDDMockito.when(reserveItemServiceClient.updateInventory(ArgumentMatchers.anyLong(), ArgumentMatchers.anyInt()))
|
BDDMockito.when(reserveItemServiceClient.updateInventory(ArgumentMatchers.anyLong(), ArgumentMatchers.anyInt()))
|
||||||
@@ -495,7 +490,7 @@ public class ReserveApiControllerTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void 예약신청_valid_실패() throws Exception {
|
public void 예약신청_valid_실패() {
|
||||||
ReserveItem validReserveItem = ReserveItem.builder()
|
ReserveItem validReserveItem = ReserveItem.builder()
|
||||||
.reserveItemId(1L)
|
.reserveItemId(1L)
|
||||||
.reserveItemName("test")
|
.reserveItemName("test")
|
||||||
@@ -532,7 +527,7 @@ public class ReserveApiControllerTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void 물품재고조회_성공() throws Exception {
|
public void 물품재고조회_성공() {
|
||||||
|
|
||||||
BDDMockito.when(reserveItemServiceClient.findById(ArgumentMatchers.anyLong()))
|
BDDMockito.when(reserveItemServiceClient.findById(ArgumentMatchers.anyLong()))
|
||||||
.thenReturn(Mono.just(ReserveItemResponseDto.builder().reserveItem(reserveItem).build()));
|
.thenReturn(Mono.just(ReserveItemResponseDto.builder().reserveItem(reserveItem).build()));
|
||||||
|
|||||||
@@ -1,15 +1,11 @@
|
|||||||
package org.egovframe.cloud.reserveitemservice;
|
package org.egovframe.cloud.reserveitemservice;
|
||||||
|
|
||||||
|
import java.security.Security;
|
||||||
import org.springframework.boot.SpringApplication;
|
import org.springframework.boot.SpringApplication;
|
||||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
|
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
|
||||||
import org.springframework.cloud.openfeign.EnableFeignClients;
|
|
||||||
import org.springframework.context.annotation.ComponentScan;
|
import org.springframework.context.annotation.ComponentScan;
|
||||||
|
|
||||||
import reactivefeign.spring.config.EnableReactiveFeignClients;
|
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.reserveitemservice"}) // org.egovframe.cloud.common package 포함하기 위해
|
@ComponentScan({"org.egovframe.cloud.common", "org.egovframe.cloud.reactive", "org.egovframe.cloud.reserveitemservice"}) // org.egovframe.cloud.common package 포함하기 위해
|
||||||
@EnableDiscoveryClient
|
@EnableDiscoveryClient
|
||||||
@@ -25,5 +21,4 @@ public class ReserveItemServiceApplication {
|
|||||||
SpringApplication.run(ReserveItemServiceApplication.class, args);
|
SpringApplication.run(ReserveItemServiceApplication.class, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package org.egovframe.cloud.reserveitemservice.api.location;
|
package org.egovframe.cloud.reserveitemservice.api.location;
|
||||||
|
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
|
import javax.validation.Valid;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.egovframe.cloud.common.dto.RequestDto;
|
import org.egovframe.cloud.common.dto.RequestDto;
|
||||||
@@ -11,12 +12,18 @@ import org.egovframe.cloud.reserveitemservice.service.location.LocationService;
|
|||||||
import org.springframework.data.domain.Page;
|
import org.springframework.data.domain.Page;
|
||||||
import org.springframework.data.domain.PageRequest;
|
import org.springframework.data.domain.PageRequest;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PathVariable;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PutMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
|
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
import reactor.core.publisher.Flux;
|
import reactor.core.publisher.Flux;
|
||||||
import reactor.core.publisher.Mono;
|
import reactor.core.publisher.Mono;
|
||||||
|
|
||||||
import javax.validation.Valid;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* org.egovframe.cloud.reserveitemservice.api.location.LocationApiController
|
* org.egovframe.cloud.reserveitemservice.api.location.LocationApiController
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
package org.egovframe.cloud.reserveitemservice.api.location.dto;
|
package org.egovframe.cloud.reserveitemservice.api.location.dto;
|
||||||
|
|
||||||
import lombok.*;
|
|
||||||
import org.egovframe.cloud.reserveitemservice.domain.location.Location;
|
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.ToString;
|
||||||
|
import org.egovframe.cloud.reserveitemservice.domain.location.Location;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* org.egovframe.cloud.reserveitemservice.api.location.dto.LocationResponseDto
|
* org.egovframe.cloud.reserveitemservice.api.location.dto.LocationResponseDto
|
||||||
|
|||||||
@@ -1,13 +1,12 @@
|
|||||||
package org.egovframe.cloud.reserveitemservice.api.location.dto;
|
package org.egovframe.cloud.reserveitemservice.api.location.dto;
|
||||||
|
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
import lombok.Builder;
|
import lombok.Builder;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
import lombok.ToString;
|
import lombok.ToString;
|
||||||
import org.egovframe.cloud.reserveitemservice.domain.location.Location;
|
import org.egovframe.cloud.reserveitemservice.domain.location.Location;
|
||||||
|
|
||||||
import javax.validation.constraints.NotNull;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* org.egovframe.cloud.reserveitemservice.api.location.dto.LocationSaveRequestDto
|
* org.egovframe.cloud.reserveitemservice.api.location.dto.LocationSaveRequestDto
|
||||||
* <p>
|
* <p>
|
||||||
|
|||||||
@@ -1,12 +1,11 @@
|
|||||||
package org.egovframe.cloud.reserveitemservice.api.location.dto;
|
package org.egovframe.cloud.reserveitemservice.api.location.dto;
|
||||||
|
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
import lombok.Builder;
|
import lombok.Builder;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
import lombok.ToString;
|
import lombok.ToString;
|
||||||
import org.egovframe.cloud.reserveitemservice.domain.location.Location;
|
import org.egovframe.cloud.reserveitemservice.domain.location.Location;
|
||||||
|
|
||||||
import javax.validation.constraints.NotNull;
|
|
||||||
/**
|
/**
|
||||||
* org.egovframe.cloud.reserveitemservice.api.location.dto.LocationUpdateRequestDto
|
* org.egovframe.cloud.reserveitemservice.api.location.dto.LocationUpdateRequestDto
|
||||||
* <p>
|
* <p>
|
||||||
|
|||||||
@@ -1,11 +1,10 @@
|
|||||||
package org.egovframe.cloud.reserveitemservice.api.reserveItem;
|
package org.egovframe.cloud.reserveitemservice.api.reserveItem;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import javax.validation.Valid;
|
import javax.validation.Valid;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.egovframe.cloud.reserveitemservice.api.reserveItem.dto.ReserveItemListResponseDto;
|
import org.egovframe.cloud.reserveitemservice.api.reserveItem.dto.ReserveItemListResponseDto;
|
||||||
import org.egovframe.cloud.reserveitemservice.api.reserveItem.dto.ReserveItemMainResponseDto;
|
import org.egovframe.cloud.reserveitemservice.api.reserveItem.dto.ReserveItemMainResponseDto;
|
||||||
import org.egovframe.cloud.reserveitemservice.api.reserveItem.dto.ReserveItemRelationResponseDto;
|
import org.egovframe.cloud.reserveitemservice.api.reserveItem.dto.ReserveItemRelationResponseDto;
|
||||||
@@ -26,10 +25,6 @@ import org.springframework.web.bind.annotation.RequestBody;
|
|||||||
import org.springframework.web.bind.annotation.RequestParam;
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
import org.springframework.web.bind.annotation.ResponseStatus;
|
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import reactor.core.publisher.Flux;
|
|
||||||
import reactor.core.publisher.Mono;
|
import reactor.core.publisher.Mono;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,14 +1,11 @@
|
|||||||
package org.egovframe.cloud.reserveitemservice.api.reserveItem.dto;
|
package org.egovframe.cloud.reserveitemservice.api.reserveItem.dto;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
import lombok.Builder;
|
import lombok.Builder;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
import lombok.ToString;
|
import lombok.ToString;
|
||||||
import org.egovframe.cloud.reserveitemservice.domain.reserveItem.ReserveItem;
|
import org.egovframe.cloud.reserveitemservice.domain.reserveItem.ReserveItem;
|
||||||
import org.springframework.util.NumberUtils;
|
|
||||||
import org.springframework.util.StringUtils;
|
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,13 +1,11 @@
|
|||||||
package org.egovframe.cloud.reserveitemservice.api.reserveItem.dto;
|
package org.egovframe.cloud.reserveitemservice.api.reserveItem.dto;
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
import org.egovframe.cloud.reserveitemservice.domain.reserveItem.ReserveItem;
|
|
||||||
|
|
||||||
import lombok.Builder;
|
import lombok.Builder;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
import lombok.ToString;
|
import lombok.ToString;
|
||||||
|
import org.egovframe.cloud.reserveitemservice.domain.reserveItem.ReserveItem;
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
|
|||||||
@@ -1,16 +1,14 @@
|
|||||||
package org.egovframe.cloud.reserveitemservice.api.reserveItem.dto;
|
package org.egovframe.cloud.reserveitemservice.api.reserveItem.dto;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
import lombok.Builder;
|
import lombok.Builder;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
import lombok.ToString;
|
import lombok.ToString;
|
||||||
|
|
||||||
import org.egovframe.cloud.reserveitemservice.domain.location.Location;
|
import org.egovframe.cloud.reserveitemservice.domain.location.Location;
|
||||||
import org.egovframe.cloud.reserveitemservice.domain.reserveItem.ReserveItem;
|
import org.egovframe.cloud.reserveitemservice.domain.reserveItem.ReserveItem;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
import java.time.LocalDateTime;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* org.egovframe.cloud.reserveitemservice.api.reserveItem.dto.ReserveItemRelationResponseDto
|
* org.egovframe.cloud.reserveitemservice.api.reserveItem.dto.ReserveItemRelationResponseDto
|
||||||
* <p>
|
* <p>
|
||||||
|
|||||||
@@ -1,6 +1,10 @@
|
|||||||
package org.egovframe.cloud.reserveitemservice.api.reserveItem.dto;
|
package org.egovframe.cloud.reserveitemservice.api.reserveItem.dto;
|
||||||
|
|
||||||
import lombok.*;
|
import java.util.Objects;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.Setter;
|
||||||
|
import lombok.ToString;
|
||||||
import org.egovframe.cloud.common.dto.RequestDto;
|
import org.egovframe.cloud.common.dto.RequestDto;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -28,4 +32,16 @@ public class ReserveItemRequestDto extends RequestDto {
|
|||||||
private Long locationId;
|
private Long locationId;
|
||||||
private String categoryId;
|
private String categoryId;
|
||||||
private Boolean isUse;
|
private Boolean isUse;
|
||||||
|
|
||||||
|
public boolean hasLocationId() {
|
||||||
|
return hasId(locationId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasCategoryId() {
|
||||||
|
return hasId(categoryId);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean hasId(Object id) {
|
||||||
|
return Objects.nonNull(id) && !Objects.equals("null", id) && !Objects.equals("undefined", id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
package org.egovframe.cloud.reserveitemservice.api.reserveItem.dto;
|
package org.egovframe.cloud.reserveitemservice.api.reserveItem.dto;
|
||||||
|
|
||||||
import lombok.*;
|
|
||||||
import lombok.experimental.Accessors;
|
|
||||||
import org.egovframe.cloud.reserveitemservice.domain.location.Location;
|
|
||||||
import org.egovframe.cloud.reserveitemservice.domain.reserveItem.ReserveItem;
|
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.ToString;
|
||||||
|
import org.egovframe.cloud.reserveitemservice.domain.reserveItem.ReserveItem;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* org.egovframe.cloud.reserveitemservice.api.reserveItem.dto.ReserveItemResponseDto
|
* org.egovframe.cloud.reserveitemservice.api.reserveItem.dto.ReserveItemResponseDto
|
||||||
|
|||||||
@@ -1,5 +1,11 @@
|
|||||||
package org.egovframe.cloud.reserveitemservice.api.reserveItem.dto;
|
package org.egovframe.cloud.reserveitemservice.api.reserveItem.dto;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import javax.validation.constraints.NotBlank;
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
|
import javax.validation.constraints.PositiveOrZero;
|
||||||
|
import javax.validation.constraints.Size;
|
||||||
import lombok.Builder;
|
import lombok.Builder;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
@@ -7,10 +13,6 @@ import lombok.ToString;
|
|||||||
import org.egovframe.cloud.reserveitemservice.domain.reserveItem.ReserveItem;
|
import org.egovframe.cloud.reserveitemservice.domain.reserveItem.ReserveItem;
|
||||||
import org.egovframe.cloud.reserveitemservice.validator.annotation.ReserveItemSaveValid;
|
import org.egovframe.cloud.reserveitemservice.validator.annotation.ReserveItemSaveValid;
|
||||||
|
|
||||||
import javax.validation.constraints.*;
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
import java.time.LocalDateTime;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* org.egovframe.cloud.reserveitemservice.api.reserveItem.dto.ReserveItemSaveRequestDto
|
* org.egovframe.cloud.reserveitemservice.api.reserveItem.dto.ReserveItemSaveRequestDto
|
||||||
* <p>
|
* <p>
|
||||||
|
|||||||
@@ -1,16 +1,17 @@
|
|||||||
package org.egovframe.cloud.reserveitemservice.api.reserveItem.dto;
|
package org.egovframe.cloud.reserveitemservice.api.reserveItem.dto;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import javax.validation.constraints.NotBlank;
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
|
import javax.validation.constraints.PositiveOrZero;
|
||||||
|
import javax.validation.constraints.Size;
|
||||||
import lombok.Builder;
|
import lombok.Builder;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
import lombok.ToString;
|
import lombok.ToString;
|
||||||
import org.egovframe.cloud.reserveitemservice.domain.reserveItem.ReserveItem;
|
import org.egovframe.cloud.reserveitemservice.domain.reserveItem.ReserveItem;
|
||||||
import org.egovframe.cloud.reserveitemservice.validator.annotation.ReserveItemSaveValid;
|
import org.egovframe.cloud.reserveitemservice.validator.annotation.ReserveItemSaveValid;
|
||||||
import org.hibernate.validator.constraints.Length;
|
|
||||||
|
|
||||||
import javax.validation.constraints.*;
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
import java.time.LocalDateTime;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* org.egovframe.cloud.reserveitemservice.api.reserveItem.dto.ReserveItemUpdateRequestDto
|
* org.egovframe.cloud.reserveitemservice.api.reserveItem.dto.ReserveItemUpdateRequestDto
|
||||||
|
|||||||
@@ -1,9 +1,12 @@
|
|||||||
package org.egovframe.cloud.reserveitemservice.api.reserveItem.dto;
|
package org.egovframe.cloud.reserveitemservice.api.reserveItem.dto;
|
||||||
|
|
||||||
import lombok.*;
|
|
||||||
|
|
||||||
import javax.validation.constraints.NotNull;
|
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.Setter;
|
||||||
|
import lombok.ToString;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* org.egovframe.cloud.reserverequestservice.api.dto.ReserveSaveRequestDto
|
* org.egovframe.cloud.reserverequestservice.api.dto.ReserveSaveRequestDto
|
||||||
|
|||||||
@@ -1,25 +1,13 @@
|
|||||||
package org.egovframe.cloud.reserveitemservice.config;
|
package org.egovframe.cloud.reserveitemservice.config;
|
||||||
|
|
||||||
|
|
||||||
|
import java.util.function.Consumer;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.egovframe.cloud.reserveitemservice.api.reserveItem.dto.ReserveSaveRequestDto;
|
import org.egovframe.cloud.reserveitemservice.api.reserveItem.dto.ReserveSaveRequestDto;
|
||||||
import org.egovframe.cloud.reserveitemservice.service.reserveItem.ReserveItemService;
|
import org.egovframe.cloud.reserveitemservice.service.reserveItem.ReserveItemService;
|
||||||
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
|
|
||||||
import org.springframework.amqp.rabbit.core.RabbitTemplate;
|
|
||||||
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
|
|
||||||
import org.springframework.amqp.support.converter.MessageConverter;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.messaging.Message;
|
|
||||||
import org.springframework.messaging.support.MessageBuilder;
|
|
||||||
import reactor.core.publisher.Flux;
|
|
||||||
import reactor.core.publisher.Mono;
|
|
||||||
import reactor.core.scheduler.Scheduler;
|
|
||||||
import reactor.core.scheduler.Schedulers;
|
|
||||||
|
|
||||||
import java.util.function.Consumer;
|
|
||||||
import java.util.function.Function;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* org.egovframe.cloud.reserverequestservice.config.ReserveEventConfig
|
* org.egovframe.cloud.reserverequestservice.config.ReserveEventConfig
|
||||||
|
|||||||
@@ -1,12 +1,10 @@
|
|||||||
package org.egovframe.cloud.reserveitemservice.config;
|
package org.egovframe.cloud.reserveitemservice.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.CircuitBreakerConfig;
|
||||||
import io.github.resilience4j.circuitbreaker.CircuitBreakerRegistry;
|
import io.github.resilience4j.circuitbreaker.CircuitBreakerRegistry;
|
||||||
|
import java.time.Duration;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* org.egovframe.cloud.portalservice.config.Resilience4JConfig
|
* org.egovframe.cloud.portalservice.config.Resilience4JConfig
|
||||||
|
|||||||
@@ -1,13 +1,15 @@
|
|||||||
package org.egovframe.cloud.reserveitemservice.domain.location;
|
package org.egovframe.cloud.reserveitemservice.domain.location;
|
||||||
|
|
||||||
import lombok.*;
|
import javax.validation.constraints.Size;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.ToString;
|
||||||
import org.egovframe.cloud.reactive.domain.BaseEntity;
|
import org.egovframe.cloud.reactive.domain.BaseEntity;
|
||||||
import org.springframework.data.annotation.Id;
|
import org.springframework.data.annotation.Id;
|
||||||
import org.springframework.data.relational.core.mapping.Column;
|
import org.springframework.data.relational.core.mapping.Column;
|
||||||
import org.springframework.data.relational.core.mapping.Table;
|
import org.springframework.data.relational.core.mapping.Table;
|
||||||
|
|
||||||
import javax.validation.constraints.Size;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* org.egovframe.cloud.reserveitemservice.domain.location.Location
|
* org.egovframe.cloud.reserveitemservice.domain.location.Location
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,8 +1,14 @@
|
|||||||
package org.egovframe.cloud.reserveitemservice.domain.reserveItem;
|
package org.egovframe.cloud.reserveitemservice.domain.reserveItem;
|
||||||
|
|
||||||
|
|
||||||
import lombok.*;
|
import java.math.BigDecimal;
|
||||||
import lombok.experimental.Accessors;
|
import java.time.LocalDateTime;
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
|
import javax.validation.constraints.Size;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.ToString;
|
||||||
import org.egovframe.cloud.reactive.domain.BaseEntity;
|
import org.egovframe.cloud.reactive.domain.BaseEntity;
|
||||||
import org.egovframe.cloud.reserveitemservice.api.reserveItem.dto.ReserveItemUpdateRequestDto;
|
import org.egovframe.cloud.reserveitemservice.api.reserveItem.dto.ReserveItemUpdateRequestDto;
|
||||||
import org.egovframe.cloud.reserveitemservice.domain.location.Location;
|
import org.egovframe.cloud.reserveitemservice.domain.location.Location;
|
||||||
@@ -11,11 +17,6 @@ import org.springframework.data.annotation.Transient;
|
|||||||
import org.springframework.data.relational.core.mapping.Column;
|
import org.springframework.data.relational.core.mapping.Column;
|
||||||
import org.springframework.data.relational.core.mapping.Table;
|
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
|
* org.egovframe.cloud.reserveitemservice.domain.reserveItem.ReserveItem
|
||||||
*
|
*
|
||||||
@@ -312,11 +313,11 @@ public class ReserveItem extends BaseEntity {
|
|||||||
/**
|
/**
|
||||||
* 재고 변경
|
* 재고 변경
|
||||||
*
|
*
|
||||||
* @param inventoryQty
|
* @param reserveQty
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public ReserveItem updateInventoryQty(Integer inventoryQty) {
|
public ReserveItem updateInventoryQty(Integer reserveQty) {
|
||||||
this.inventoryQty = inventoryQty;
|
this.inventoryQty = calcInventoryQty(reserveQty);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -371,6 +372,31 @@ public class ReserveItem extends BaseEntity {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String validate(int reserveQty) {
|
||||||
|
if (!Category.EDUCATION.isEquals(categoryId)) {
|
||||||
|
//해당 예약은 수정할 수 없습니다.
|
||||||
|
return "valid.reserve_not_update";
|
||||||
|
}
|
||||||
|
|
||||||
|
LocalDateTime now = LocalDateTime.now();
|
||||||
|
if (!(now.isAfter(requestStartDate) && now.isBefore(requestEndDate))) {
|
||||||
|
//해당 날짜에는 예약할 수 없습니다.
|
||||||
|
return "valid.reserve_date";
|
||||||
|
}
|
||||||
|
|
||||||
|
int qty = calcInventoryQty(reserveQty);
|
||||||
|
if (qty < 0) {
|
||||||
|
//해당 날짜에 예약할 수 있는 재고수량이 없습니다.
|
||||||
|
return "valid.reserve_count";
|
||||||
|
}
|
||||||
|
|
||||||
|
return "valid";
|
||||||
|
}
|
||||||
|
|
||||||
|
private int calcInventoryQty(int reserveQty) {
|
||||||
|
return inventoryQty - reserveQty;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package org.egovframe.cloud.reserveitemservice.domain.reserveItem;
|
package org.egovframe.cloud.reserveitemservice.domain.reserveItem;
|
||||||
|
|
||||||
import org.springframework.data.r2dbc.repository.R2dbcRepository;
|
import org.springframework.data.r2dbc.repository.R2dbcRepository;
|
||||||
import reactor.core.publisher.Flux;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* org.egovframe.cloud.reserveitemservice.domain.reserveItem.ReserveItemRepository
|
* org.egovframe.cloud.reserveitemservice.domain.reserveItem.ReserveItemRepository
|
||||||
|
|||||||
@@ -1,12 +1,8 @@
|
|||||||
package org.egovframe.cloud.reserveitemservice.domain.reserveItem;
|
package org.egovframe.cloud.reserveitemservice.domain.reserveItem;
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
|
||||||
|
|
||||||
import org.egovframe.cloud.reserveitemservice.api.reserveItem.dto.ReserveItemMainResponseDto;
|
|
||||||
import org.egovframe.cloud.reserveitemservice.api.reserveItem.dto.ReserveItemRequestDto;
|
import org.egovframe.cloud.reserveitemservice.api.reserveItem.dto.ReserveItemRequestDto;
|
||||||
import org.egovframe.cloud.reserveitemservice.domain.code.Code;
|
import org.egovframe.cloud.reserveitemservice.domain.code.Code;
|
||||||
import org.springframework.data.domain.Pageable;
|
import org.springframework.data.domain.Pageable;
|
||||||
|
|
||||||
import reactor.core.publisher.Flux;
|
import reactor.core.publisher.Flux;
|
||||||
import reactor.core.publisher.Mono;
|
import reactor.core.publisher.Mono;
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
package org.egovframe.cloud.reserveitemservice.domain.reserveItem;
|
package org.egovframe.cloud.reserveitemservice.domain.reserveItem;
|
||||||
|
|
||||||
import static org.springframework.data.relational.core.query.Criteria.*;
|
import static org.springframework.data.relational.core.query.Criteria.where;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.egovframe.cloud.reserveitemservice.api.reserveItem.dto.ReserveItemRequestDto;
|
import org.egovframe.cloud.reserveitemservice.api.reserveItem.dto.ReserveItemRequestDto;
|
||||||
import org.egovframe.cloud.reserveitemservice.domain.code.Code;
|
import org.egovframe.cloud.reserveitemservice.domain.code.Code;
|
||||||
import org.egovframe.cloud.reserveitemservice.domain.location.Location;
|
import org.egovframe.cloud.reserveitemservice.domain.location.Location;
|
||||||
@@ -14,9 +15,6 @@ import org.springframework.data.r2dbc.core.R2dbcEntityTemplate;
|
|||||||
import org.springframework.data.relational.core.query.Criteria;
|
import org.springframework.data.relational.core.query.Criteria;
|
||||||
import org.springframework.data.relational.core.query.Query;
|
import org.springframework.data.relational.core.query.Query;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import reactor.core.publisher.Flux;
|
import reactor.core.publisher.Flux;
|
||||||
import reactor.core.publisher.Mono;
|
import reactor.core.publisher.Mono;
|
||||||
|
|
||||||
@@ -40,7 +38,7 @@ import reactor.core.publisher.Mono;
|
|||||||
@Slf4j
|
@Slf4j
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class ReserveItemRepositoryImpl implements ReserveItemRepositoryCustom{
|
public class ReserveItemRepositoryImpl implements ReserveItemRepositoryCustom{
|
||||||
|
private static final String SORT_COLUMN = "create_date";
|
||||||
private final R2dbcEntityTemplate entityTemplate;
|
private final R2dbcEntityTemplate entityTemplate;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -54,7 +52,7 @@ public class ReserveItemRepositoryImpl implements ReserveItemRepositoryCustom{
|
|||||||
public Flux<ReserveItem> search(ReserveItemRequestDto requestDto, Pageable pageable) {
|
public Flux<ReserveItem> search(ReserveItemRequestDto requestDto, Pageable pageable) {
|
||||||
return entityTemplate.select(ReserveItem.class)
|
return entityTemplate.select(ReserveItem.class)
|
||||||
.matching(Query.query(Criteria.from(whereQuery(requestDto)))
|
.matching(Query.query(Criteria.from(whereQuery(requestDto)))
|
||||||
.sort(Sort.by(Sort.Direction.DESC, "create_date"))
|
.sort(Sort.by(Sort.Direction.DESC, SORT_COLUMN))
|
||||||
.with(pageable))
|
.with(pageable))
|
||||||
.all()
|
.all()
|
||||||
.flatMap(this::loadRelations)
|
.flatMap(this::loadRelations)
|
||||||
@@ -72,7 +70,7 @@ public class ReserveItemRepositoryImpl implements ReserveItemRepositoryCustom{
|
|||||||
public Mono<Long> searchCount(ReserveItemRequestDto requestDto, Pageable pageable) {
|
public Mono<Long> searchCount(ReserveItemRequestDto requestDto, Pageable pageable) {
|
||||||
return entityTemplate.select(ReserveItem.class)
|
return entityTemplate.select(ReserveItem.class)
|
||||||
.matching(Query.query(Criteria.from(whereQuery(requestDto)))
|
.matching(Query.query(Criteria.from(whereQuery(requestDto)))
|
||||||
.sort(Sort.by(Sort.Direction.DESC, "create_date"))
|
.sort(Sort.by(Sort.Direction.DESC, SORT_COLUMN))
|
||||||
.with(pageable))
|
.with(pageable))
|
||||||
.count();
|
.count();
|
||||||
}
|
}
|
||||||
@@ -101,7 +99,7 @@ public class ReserveItemRepositoryImpl implements ReserveItemRepositoryCustom{
|
|||||||
@Override
|
@Override
|
||||||
public Flux<ReserveItem> findLatestByCategory(Integer count, String categoryId) {
|
public Flux<ReserveItem> findLatestByCategory(Integer count, String categoryId) {
|
||||||
Query query =Query.query(where("category_id").is(categoryId)
|
Query query =Query.query(where("category_id").is(categoryId)
|
||||||
.and("use_at").isTrue()).sort(Sort.by(Sort.Order.desc("create_date")));
|
.and("use_at").isTrue()).sort(Sort.by(Sort.Order.desc(SORT_COLUMN)));
|
||||||
|
|
||||||
if (count > 0) {
|
if (count > 0) {
|
||||||
query.limit(count);
|
query.limit(count);
|
||||||
@@ -216,17 +214,15 @@ public class ReserveItemRepositoryImpl implements ReserveItemRepositoryCustom{
|
|||||||
|
|
||||||
List<Criteria> whereCriteria = new ArrayList<>();
|
List<Criteria> whereCriteria = new ArrayList<>();
|
||||||
|
|
||||||
if (StringUtils.hasText(keyword)) {
|
if (StringUtils.hasText(keyword) && "item".equals(keywordType)) {
|
||||||
if ("item".equals(keywordType)) {
|
|
||||||
whereCriteria.add(where("reserve_item_name").like(likeText(keyword)));
|
whereCriteria.add(where("reserve_item_name").like(likeText(keyword)));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (requestDto.getLocationId() != null && !"null".equals(requestDto.getLocationId()) && !"undefined".equals(requestDto.getLocationId())) {
|
if (requestDto.hasLocationId()) {
|
||||||
whereCriteria.add(where("location_id").in(requestDto.getLocationId()));
|
whereCriteria.add(where("location_id").in(requestDto.getLocationId()));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (requestDto.getCategoryId() != null && !"null".equals(requestDto.getCategoryId()) && !"undefined".equals(requestDto.getCategoryId())) {
|
if (requestDto.hasCategoryId()) {
|
||||||
whereCriteria.add(where("category_id").in(requestDto.getCategoryId()));
|
whereCriteria.add(where("category_id").in(requestDto.getCategoryId()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,9 +4,6 @@ import lombok.RequiredArgsConstructor;
|
|||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.egovframe.cloud.common.dto.RequestDto;
|
import org.egovframe.cloud.common.dto.RequestDto;
|
||||||
import org.egovframe.cloud.common.exception.BusinessMessageException;
|
import org.egovframe.cloud.common.exception.BusinessMessageException;
|
||||||
import org.egovframe.cloud.common.exception.EntityNotFoundException;
|
|
||||||
import org.egovframe.cloud.common.service.AbstractService;
|
|
||||||
import org.egovframe.cloud.common.util.MessageUtil;
|
|
||||||
import org.egovframe.cloud.reactive.service.ReactiveAbstractService;
|
import org.egovframe.cloud.reactive.service.ReactiveAbstractService;
|
||||||
import org.egovframe.cloud.reserveitemservice.api.location.dto.LocationResponseDto;
|
import org.egovframe.cloud.reserveitemservice.api.location.dto.LocationResponseDto;
|
||||||
import org.egovframe.cloud.reserveitemservice.api.location.dto.LocationSaveRequestDto;
|
import org.egovframe.cloud.reserveitemservice.api.location.dto.LocationSaveRequestDto;
|
||||||
|
|||||||
@@ -1,12 +1,10 @@
|
|||||||
package org.egovframe.cloud.reserveitemservice.service.reserveItem;
|
package org.egovframe.cloud.reserveitemservice.service.reserveItem;
|
||||||
|
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
import java.time.LocalDateTime;
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.egovframe.cloud.common.exception.BusinessMessageException;
|
import org.egovframe.cloud.common.exception.BusinessMessageException;
|
||||||
import org.egovframe.cloud.reactive.service.ReactiveAbstractService;
|
import org.egovframe.cloud.reactive.service.ReactiveAbstractService;
|
||||||
import org.egovframe.cloud.reserveitemservice.api.reserveItem.dto.ReserveItemListResponseDto;
|
import org.egovframe.cloud.reserveitemservice.api.reserveItem.dto.ReserveItemListResponseDto;
|
||||||
@@ -17,7 +15,6 @@ import org.egovframe.cloud.reserveitemservice.api.reserveItem.dto.ReserveItemRes
|
|||||||
import org.egovframe.cloud.reserveitemservice.api.reserveItem.dto.ReserveItemSaveRequestDto;
|
import org.egovframe.cloud.reserveitemservice.api.reserveItem.dto.ReserveItemSaveRequestDto;
|
||||||
import org.egovframe.cloud.reserveitemservice.api.reserveItem.dto.ReserveItemUpdateRequestDto;
|
import org.egovframe.cloud.reserveitemservice.api.reserveItem.dto.ReserveItemUpdateRequestDto;
|
||||||
import org.egovframe.cloud.reserveitemservice.config.RequestMessage;
|
import org.egovframe.cloud.reserveitemservice.config.RequestMessage;
|
||||||
import org.egovframe.cloud.reserveitemservice.domain.reserveItem.Category;
|
|
||||||
import org.egovframe.cloud.reserveitemservice.domain.reserveItem.ReserveItem;
|
import org.egovframe.cloud.reserveitemservice.domain.reserveItem.ReserveItem;
|
||||||
import org.egovframe.cloud.reserveitemservice.domain.reserveItem.ReserveItemRepository;
|
import org.egovframe.cloud.reserveitemservice.domain.reserveItem.ReserveItemRepository;
|
||||||
import org.springframework.cloud.stream.function.StreamBridge;
|
import org.springframework.cloud.stream.function.StreamBridge;
|
||||||
@@ -27,10 +24,6 @@ import org.springframework.data.domain.Pageable;
|
|||||||
import org.springframework.messaging.support.MessageBuilder;
|
import org.springframework.messaging.support.MessageBuilder;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import reactor.core.publisher.Flux;
|
|
||||||
import reactor.core.publisher.Mono;
|
import reactor.core.publisher.Mono;
|
||||||
import reactor.core.scheduler.Schedulers;
|
import reactor.core.scheduler.Schedulers;
|
||||||
|
|
||||||
@@ -58,31 +51,14 @@ import reactor.core.scheduler.Schedulers;
|
|||||||
public class ReserveItemService extends ReactiveAbstractService {
|
public class ReserveItemService extends ReactiveAbstractService {
|
||||||
|
|
||||||
private static final String RESERVE_CATEGORY_CODE = "reserve-category";
|
private static final String RESERVE_CATEGORY_CODE = "reserve-category";
|
||||||
|
private static final String RESERVE_CATEGORY_CODE_ALL = "all";
|
||||||
|
private static final String INVENTORY_UPDATED_BINDING_NAME = "inventoryUpdated-out-0";
|
||||||
|
private static final String EVENT_HEADER_NAME = "reserveUUID";
|
||||||
|
|
||||||
private final ReserveItemRepository reserveItemRepository;
|
private final ReserveItemRepository reserveItemRepository;
|
||||||
private final StreamBridge streamBridge;
|
private final StreamBridge streamBridge;
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* entity -> dto 변환
|
|
||||||
*
|
|
||||||
* @param reserveItem
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
private Mono<ReserveItemResponseDto> convertReserveItemResponseDto(ReserveItem reserveItem) {
|
|
||||||
return Mono.just(ReserveItemResponseDto.builder().reserveItem(reserveItem).build());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* entity -> dto 변환
|
|
||||||
*
|
|
||||||
* @param reserveItem
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
private Mono<ReserveItemListResponseDto> convertReserveItemListResponseDto(ReserveItem reserveItem) {
|
|
||||||
return Mono.just(ReserveItemListResponseDto.builder().entity(reserveItem).build());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 목록 조회
|
* 목록 조회
|
||||||
*
|
*
|
||||||
@@ -109,7 +85,7 @@ public class ReserveItemService extends ReactiveAbstractService {
|
|||||||
*/
|
*/
|
||||||
@Transactional(readOnly = true)
|
@Transactional(readOnly = true)
|
||||||
public Mono<Page<ReserveItemListResponseDto>> searchForUser(String categoryId, ReserveItemRequestDto requestDto, Pageable pageable) {
|
public Mono<Page<ReserveItemListResponseDto>> searchForUser(String categoryId, ReserveItemRequestDto requestDto, Pageable pageable) {
|
||||||
if (!"all".equals(categoryId)) {
|
if (!RESERVE_CATEGORY_CODE_ALL.equals(categoryId)) {
|
||||||
requestDto.setCategoryId(categoryId);
|
requestDto.setCategoryId(categoryId);
|
||||||
}
|
}
|
||||||
return reserveItemRepository.search(requestDto, pageable)
|
return reserveItemRepository.search(requestDto, pageable)
|
||||||
@@ -203,24 +179,11 @@ public class ReserveItemService extends ReactiveAbstractService {
|
|||||||
return reserveItemRepository.findById(reserveItemId)
|
return reserveItemRepository.findById(reserveItemId)
|
||||||
.switchIfEmpty(monoResponseStatusEntityNotFoundException(reserveItemId))
|
.switchIfEmpty(monoResponseStatusEntityNotFoundException(reserveItemId))
|
||||||
.flatMap(reserveItem -> {
|
.flatMap(reserveItem -> {
|
||||||
if (!Category.EDUCATION.isEquals(reserveItem.getCategoryId())) {
|
String validate = reserveItem.validate(reserveQty);
|
||||||
//해당 예약은 수정할 수 없습니다.
|
if (!"valid".equals(validate)) {
|
||||||
return Mono.error(new BusinessMessageException(getMessage("valid.reserve_not_update")));
|
return Mono.error(new BusinessMessageException(getMessage(validate)));
|
||||||
}
|
}
|
||||||
|
return Mono.just(reserveItem.updateInventoryQty(reserveQty));
|
||||||
LocalDateTime now = LocalDateTime.now();
|
|
||||||
if (!(now.isAfter(reserveItem.getRequestStartDate()) && now.isBefore(reserveItem.getRequestEndDate()))) {
|
|
||||||
//해당 날짜에는 예약할 수 없습니다.
|
|
||||||
return Mono.error(new BusinessMessageException(getMessage("valid.reserve_date")));
|
|
||||||
}
|
|
||||||
|
|
||||||
int qty = reserveItem.getInventoryQty() - reserveQty;
|
|
||||||
if (qty < 0) {
|
|
||||||
//해당 날짜에 예약할 수 있는 재고수량이 없습니다.
|
|
||||||
return Mono.error(new BusinessMessageException(getMessage("valid.reserve_count")));
|
|
||||||
}
|
|
||||||
|
|
||||||
return Mono.just(reserveItem.updateInventoryQty(qty));
|
|
||||||
})
|
})
|
||||||
.flatMap(reserveItemRepository::save)
|
.flatMap(reserveItemRepository::save)
|
||||||
.delayElement(Duration.ofSeconds(5))
|
.delayElement(Duration.ofSeconds(5))
|
||||||
@@ -236,23 +199,6 @@ public class ReserveItemService extends ReactiveAbstractService {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 재고 변경 성공 여부 이벤트 발생
|
|
||||||
*
|
|
||||||
* @param reserveId
|
|
||||||
* @param isItemUpdated
|
|
||||||
*/
|
|
||||||
private void sendMessage(String reserveId, Boolean isItemUpdated) {
|
|
||||||
streamBridge.send("inventoryUpdated-out-0",
|
|
||||||
MessageBuilder.withPayload(
|
|
||||||
RequestMessage.builder()
|
|
||||||
.reserveId(reserveId)
|
|
||||||
.isItemUpdated(isItemUpdated)
|
|
||||||
.build())
|
|
||||||
.setHeader("reserveUUID", reserveId).build());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 한건 조회 - 연관된 데이터도 같이 조회 (e.g. codename, location)
|
* 한건 조회 - 연관된 데이터도 같이 조회 (e.g. codename, location)
|
||||||
*
|
*
|
||||||
@@ -274,13 +220,48 @@ public class ReserveItemService extends ReactiveAbstractService {
|
|||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public Mono<Map<String, Collection<ReserveItemMainResponseDto>>> findLatest(Integer count) {
|
public Mono<Map<String, Collection<ReserveItemMainResponseDto>>> findLatest(Integer count) {
|
||||||
return reserveItemRepository.findCodeDetail(
|
return reserveItemRepository.findCodeDetail(RESERVE_CATEGORY_CODE)
|
||||||
RESERVE_CATEGORY_CODE)
|
|
||||||
.flatMap(code -> reserveItemRepository.findLatestByCategory(count, code.getCodeId()))
|
.flatMap(code -> reserveItemRepository.findLatestByCategory(count, code.getCodeId()))
|
||||||
.map(reserveItem -> ReserveItemMainResponseDto.builder().entity(reserveItem).build())
|
.map(reserveItem -> ReserveItemMainResponseDto.builder().entity(reserveItem).build())
|
||||||
.collectMultimap(reserveItem -> reserveItem.getCategoryName());
|
.collectMultimap(ReserveItemMainResponseDto::getCategoryName);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* entity -> dto 변환
|
||||||
|
*
|
||||||
|
* @param reserveItem
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private Mono<ReserveItemResponseDto> convertReserveItemResponseDto(ReserveItem reserveItem) {
|
||||||
|
return Mono.just(ReserveItemResponseDto.builder().reserveItem(reserveItem).build());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* entity -> dto 변환
|
||||||
|
*
|
||||||
|
* @param reserveItem
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private Mono<ReserveItemListResponseDto> convertReserveItemListResponseDto(ReserveItem reserveItem) {
|
||||||
|
return Mono.just(ReserveItemListResponseDto.builder().entity(reserveItem).build());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 재고 변경 성공 여부 이벤트 발생
|
||||||
|
*
|
||||||
|
* @param reserveId
|
||||||
|
* @param isItemUpdated
|
||||||
|
*/
|
||||||
|
private void sendMessage(String reserveId, Boolean isItemUpdated) {
|
||||||
|
streamBridge.send(INVENTORY_UPDATED_BINDING_NAME,
|
||||||
|
MessageBuilder.withPayload(
|
||||||
|
RequestMessage.builder()
|
||||||
|
.reserveId(reserveId)
|
||||||
|
.isItemUpdated(isItemUpdated)
|
||||||
|
.build())
|
||||||
|
.setHeader(EVENT_HEADER_NAME, reserveId).build());
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,21 +1,19 @@
|
|||||||
package org.egovframe.cloud.reserveitemservice.validator;
|
package org.egovframe.cloud.reserveitemservice.validator;
|
||||||
|
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import javax.validation.ConstraintValidator;
|
||||||
|
import javax.validation.ConstraintValidatorContext;
|
||||||
import lombok.SneakyThrows;
|
import lombok.SneakyThrows;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
import org.egovframe.cloud.common.util.MessageUtil;
|
import org.egovframe.cloud.common.util.MessageUtil;
|
||||||
import org.egovframe.cloud.reserveitemservice.validator.annotation.ReserveItemSaveValid;
|
import org.egovframe.cloud.reserveitemservice.validator.annotation.ReserveItemSaveValid;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
|
||||||
import javax.validation.ConstraintValidator;
|
|
||||||
import javax.validation.ConstraintValidatorContext;
|
|
||||||
import java.lang.reflect.Field;
|
|
||||||
import java.time.LocalDateTime;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* org.egovframe.cloud.reserveitemservice.validator.ReserveItemSaveValidator
|
* org.egovframe.cloud.reserveitemservice.validator.ReserveItemSaveValidator
|
||||||
*
|
* <p>
|
||||||
* 예약 물품 저장 시 validation check를 하기 위한 custom validator
|
* 예약 물품 저장 시 validation check를 하기 위한 custom validator
|
||||||
*
|
*
|
||||||
* @author 표준프레임워크센터 shinmj
|
* @author 표준프레임워크센터 shinmj
|
||||||
@@ -39,6 +37,7 @@ public class ReserveItemSaveValidator implements ConstraintValidator<ReserveItem
|
|||||||
protected MessageUtil messageUtil;
|
protected MessageUtil messageUtil;
|
||||||
|
|
||||||
private String message;
|
private String message;
|
||||||
|
private boolean fieldValid;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void initialize(ReserveItemSaveValid constraintAnnotation) {
|
public void initialize(ReserveItemSaveValid constraintAnnotation) {
|
||||||
@@ -55,127 +54,281 @@ public class ReserveItemSaveValidator implements ConstraintValidator<ReserveItem
|
|||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
@Override
|
@Override
|
||||||
public boolean isValid(Object value, ConstraintValidatorContext context) {
|
public boolean isValid(Object value, ConstraintValidatorContext context) {
|
||||||
boolean fieldValid = true;
|
fieldValid = true;
|
||||||
|
|
||||||
// 운영 시작일, 종료일 체크
|
// 운영 시작일, 종료일 체크
|
||||||
LocalDateTime operationStartDate = (LocalDateTime) getFieldValue(value, "operationStartDate");
|
validateOperationDate(value, context);
|
||||||
LocalDateTime operationEndDate = (LocalDateTime) getFieldValue(value, "operationEndDate");
|
|
||||||
if (operationStartDate.isAfter(operationEndDate)) {
|
// 유료인 경우 이용 요금 필수
|
||||||
context.disableDefaultConstraintViolation();
|
validatePaid(value, context);
|
||||||
//시작일, 종료일, {0}이 {1}보다 늦습니다.
|
|
||||||
context.buildConstraintViolationWithTemplate(messageUtil.getMessage("valid.to_be_slow.format", new Object[]{messageUtil.getMessage("common.start_date"), messageUtil.getMessage("common.end_date")}))
|
|
||||||
.addPropertyNode("operationStartDate")
|
|
||||||
.addConstraintViolation();
|
|
||||||
fieldValid = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
String reserveMethodId = String.valueOf(getFieldValue(value, "reserveMethodId"));
|
String reserveMethodId = String.valueOf(getFieldValue(value, "reserveMethodId"));
|
||||||
//예약 방법이 '인터넷' 인경우
|
//예약 방법이 '인터넷' 인경우
|
||||||
if ("internet".equals(reserveMethodId)) {
|
if ("internet".equals(reserveMethodId)) {
|
||||||
|
return validateInternet(value, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ("telephone".equals(reserveMethodId)) {
|
||||||
|
return validateTelephone(value, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ("visit".equals(reserveMethodId)) {
|
||||||
|
return validateVisit(value, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
return fieldValid;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 운영 시작일, 종료일 체크
|
||||||
|
*
|
||||||
|
* @param value
|
||||||
|
* @param context
|
||||||
|
* @return
|
||||||
|
* @throws NoSuchFieldException
|
||||||
|
* @throws IllegalAccessException
|
||||||
|
*/
|
||||||
|
private void validateOperationDate(Object value, ConstraintValidatorContext context)
|
||||||
|
throws NoSuchFieldException, IllegalAccessException {
|
||||||
|
LocalDateTime operationStartDate = (LocalDateTime) getFieldValue(value,
|
||||||
|
"operationStartDate");
|
||||||
|
LocalDateTime operationEndDate = (LocalDateTime) getFieldValue(value, "operationEndDate");
|
||||||
|
|
||||||
|
if (operationStartDate.isAfter(operationEndDate)) {
|
||||||
|
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("operationStartDate")
|
||||||
|
.addConstraintViolation();
|
||||||
|
fieldValid = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 유료인 경우 이용 요금 필수
|
||||||
|
*
|
||||||
|
* @param value
|
||||||
|
* @param context
|
||||||
|
* @return
|
||||||
|
* @throws NoSuchFieldException
|
||||||
|
* @throws IllegalAccessException
|
||||||
|
*/
|
||||||
|
private void validatePaid(Object value, ConstraintValidatorContext context)
|
||||||
|
throws NoSuchFieldException, IllegalAccessException {
|
||||||
|
Boolean isPaid = Boolean.valueOf(String.valueOf(getFieldValue(value, "isPaid")));
|
||||||
|
if (isPaid && isNull(value, "usageCost")) {
|
||||||
|
context.disableDefaultConstraintViolation();
|
||||||
|
//이용요금 값은 필수입니다.
|
||||||
|
context.buildConstraintViolationWithTemplate(
|
||||||
|
messageUtil.getMessage("reserve_item.usage_fee") + messageUtil
|
||||||
|
.getMessage("valid.required"))
|
||||||
|
.addPropertyNode("usageCost")
|
||||||
|
.addConstraintViolation();
|
||||||
|
fieldValid = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 예약 방법인 '방문'인 경우 주소 필수
|
||||||
|
*
|
||||||
|
* @param value
|
||||||
|
* @param context
|
||||||
|
* @return
|
||||||
|
* @throws NoSuchFieldException
|
||||||
|
* @throws IllegalAccessException
|
||||||
|
*/
|
||||||
|
private boolean validateVisit(Object value, ConstraintValidatorContext context)
|
||||||
|
throws NoSuchFieldException, IllegalAccessException {
|
||||||
|
if (isNull(value, "address")) {
|
||||||
|
context.disableDefaultConstraintViolation();
|
||||||
|
//주소 값은 필수 입니다.
|
||||||
|
context.buildConstraintViolationWithTemplate(
|
||||||
|
messageUtil.getMessage("common.address") + messageUtil.getMessage("valid.required"))
|
||||||
|
.addPropertyNode("address")
|
||||||
|
.addConstraintViolation();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return fieldValid;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 예약 방법인 '전화'인 경우 contact 필수
|
||||||
|
*
|
||||||
|
* @param value
|
||||||
|
* @param context
|
||||||
|
* @return
|
||||||
|
* @throws NoSuchFieldException
|
||||||
|
* @throws IllegalAccessException
|
||||||
|
*/
|
||||||
|
private boolean validateTelephone(Object value, ConstraintValidatorContext context)
|
||||||
|
throws NoSuchFieldException, IllegalAccessException {
|
||||||
|
|
||||||
|
if (isNull(value, "contact")) {
|
||||||
|
context.disableDefaultConstraintViolation();
|
||||||
|
//문의처 값은 필수입니다.
|
||||||
|
context.buildConstraintViolationWithTemplate(
|
||||||
|
messageUtil.getMessage("reserve_item.contact") + messageUtil
|
||||||
|
.getMessage("valid.required"))
|
||||||
|
.addPropertyNode("contact")
|
||||||
|
.addConstraintViolation();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return fieldValid;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 인터넷 예약인 경우 정합성 체크
|
||||||
|
*
|
||||||
|
* @param value
|
||||||
|
* @param context
|
||||||
|
* @return
|
||||||
|
* @throws NoSuchFieldException
|
||||||
|
* @throws IllegalAccessException
|
||||||
|
*/
|
||||||
|
private boolean validateInternet(Object value, ConstraintValidatorContext context)
|
||||||
|
throws NoSuchFieldException, IllegalAccessException {
|
||||||
// 예약 구분 필수
|
// 예약 구분 필수
|
||||||
if (isNull(value, "reserveMeansId")) {
|
if (isNull(value, "reserveMeansId")) {
|
||||||
context.disableDefaultConstraintViolation();
|
context.disableDefaultConstraintViolation();
|
||||||
//인터넷 예약 구분 값은 필수 입니다.
|
//인터넷 예약 구분 값은 필수 입니다.
|
||||||
context.buildConstraintViolationWithTemplate(messageUtil.getMessage("reserve_item.reserve_means")+ messageUtil.getMessage("valid.required"))
|
context.buildConstraintViolationWithTemplate(
|
||||||
|
messageUtil.getMessage("reserve_item.reserve_means") + messageUtil
|
||||||
|
.getMessage("valid.required"))
|
||||||
.addPropertyNode("reserveMeansId")
|
.addPropertyNode("reserveMeansId")
|
||||||
.addConstraintViolation();
|
.addConstraintViolation();
|
||||||
fieldValid = false;
|
return false;
|
||||||
}else {
|
}
|
||||||
|
|
||||||
String reserveMeansId = String.valueOf(getFieldValue(value, "reserveMeansId"));
|
String reserveMeansId = String.valueOf(getFieldValue(value, "reserveMeansId"));
|
||||||
//예약 구분이 실시간 인 경우
|
//예약 구분이 실시간 인 경우
|
||||||
if ("realtime".equals(reserveMeansId)) {
|
if ("realtime".equals(reserveMeansId)) {
|
||||||
// 예약 신청 기간 필수
|
return validateRealTime(value, context);
|
||||||
if (isNull(value, "requestStartDate")) {
|
}
|
||||||
context.disableDefaultConstraintViolation();
|
|
||||||
// 예약 신청 시작일 값은 필수 입니다.
|
|
||||||
context.buildConstraintViolationWithTemplate(messageUtil.getMessage("reserve_item.request")+" "+messageUtil.getMessage("common.start_datetime") + messageUtil.getMessage("valid.required"))
|
|
||||||
.addPropertyNode("requestStartDate")
|
|
||||||
.addConstraintViolation();
|
|
||||||
|
|
||||||
fieldValid = false;
|
if ("external".equals(reserveMeansId)) {
|
||||||
} else if (isNull(value, "requestEndDate")) {
|
//예약 구분이 외부 링크인 경우 외부 링크 url 필수
|
||||||
|
if (isNull(value, "externalUrl")) {
|
||||||
context.disableDefaultConstraintViolation();
|
context.disableDefaultConstraintViolation();
|
||||||
// 예약 신청 종료일 값은 필수 입니다.
|
//외부링크 URL 값은 필수 입니다.
|
||||||
context.buildConstraintViolationWithTemplate(messageUtil.getMessage("reserve_item.request")+" "+messageUtil.getMessage("common.end_datetime") + messageUtil.getMessage("valid.required"))
|
context.buildConstraintViolationWithTemplate(
|
||||||
.addPropertyNode("requestEndDate")
|
messageUtil.getMessage("reserve_item.external_url") + messageUtil
|
||||||
|
.getMessage("valid.required"))
|
||||||
|
.addPropertyNode("externalUrl")
|
||||||
.addConstraintViolation();
|
.addConstraintViolation();
|
||||||
fieldValid = false;
|
return false;
|
||||||
}else {
|
|
||||||
LocalDateTime requestStartDate = (LocalDateTime) getFieldValue(value, "requestStartDate");
|
|
||||||
LocalDateTime requestEndDate = (LocalDateTime) getFieldValue(value, "requestEndDate");
|
|
||||||
if (requestStartDate.isAfter(requestEndDate)) {
|
|
||||||
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("requestStartDate")
|
|
||||||
.addConstraintViolation();
|
|
||||||
fieldValid = false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return fieldValid;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 실시간 인 경우 정합성 체크
|
||||||
|
*
|
||||||
|
* @param value
|
||||||
|
* @param context
|
||||||
|
* @return
|
||||||
|
* @throws NoSuchFieldException
|
||||||
|
* @throws IllegalAccessException
|
||||||
|
*/
|
||||||
|
private boolean validateRealTime(Object value, ConstraintValidatorContext context)
|
||||||
|
throws NoSuchFieldException, IllegalAccessException {
|
||||||
|
// 예약 신청 기간 필수
|
||||||
|
fieldValid = validateRequestDate(value, context);
|
||||||
|
|
||||||
//기간 지정 필수
|
//기간 지정 필수
|
||||||
|
fieldValid = validatePeriod(value, context);
|
||||||
|
|
||||||
|
return fieldValid;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 기간 지정 정합성 체크
|
||||||
|
*
|
||||||
|
* @param value
|
||||||
|
* @param context
|
||||||
|
* @throws NoSuchFieldException
|
||||||
|
* @throws IllegalAccessException
|
||||||
|
*/
|
||||||
|
private boolean validatePeriod(Object value, ConstraintValidatorContext context)
|
||||||
|
throws NoSuchFieldException, IllegalAccessException {
|
||||||
if (isNull(value, "isPeriod")) {
|
if (isNull(value, "isPeriod")) {
|
||||||
context.disableDefaultConstraintViolation();
|
context.disableDefaultConstraintViolation();
|
||||||
//기간 지정 가능 여부 값은 필수 입니다.
|
//기간 지정 가능 여부 값은 필수 입니다.
|
||||||
context.buildConstraintViolationWithTemplate(messageUtil.getMessage("reserve_item.period_possible")+ messageUtil.getMessage("valid.required"))
|
context.buildConstraintViolationWithTemplate(
|
||||||
|
messageUtil.getMessage("reserve_item.period_possible") + messageUtil
|
||||||
|
.getMessage("valid.required"))
|
||||||
.addPropertyNode("requestEndDate")
|
.addPropertyNode("requestEndDate")
|
||||||
.addConstraintViolation();
|
.addConstraintViolation();
|
||||||
fieldValid = false;
|
return false;
|
||||||
}else {
|
}
|
||||||
|
|
||||||
Boolean isPeriod = Boolean.valueOf(String.valueOf(getFieldValue(value, "isPeriod")));
|
Boolean isPeriod = Boolean.valueOf(String.valueOf(getFieldValue(value, "isPeriod")));
|
||||||
// 기간 지정 가능인 경우 최대 얘약일 수 필수
|
// 기간 지정 가능인 경우 최대 얘약일 수 필수
|
||||||
if (isPeriod && isNull(value, "periodMaxCount")) {
|
if (isPeriod && isNull(value, "periodMaxCount")) {
|
||||||
context.disableDefaultConstraintViolation();
|
context.disableDefaultConstraintViolation();
|
||||||
//최대 예약 가능 일수 값은 필수 입니다.
|
//최대 예약 가능 일수 값은 필수 입니다.
|
||||||
context.buildConstraintViolationWithTemplate(messageUtil.getMessage("reserve_item.max_period_days")+ messageUtil.getMessage("valid.required"))
|
context.buildConstraintViolationWithTemplate(
|
||||||
|
messageUtil.getMessage("reserve_item.max_period_days") + messageUtil
|
||||||
|
.getMessage("valid.required"))
|
||||||
.addPropertyNode("periodMaxCount")
|
.addPropertyNode("periodMaxCount")
|
||||||
.addConstraintViolation();
|
.addConstraintViolation();
|
||||||
fieldValid = false;
|
return false;
|
||||||
}
|
|
||||||
}
|
|
||||||
}else if ("external".equals(reserveMeansId)) {
|
|
||||||
//예약 구분이 외부 링크인 경우 외부 링크 url 필수
|
|
||||||
if (isNull(value, "externalUrl")) {
|
|
||||||
context.disableDefaultConstraintViolation();
|
|
||||||
//외부링크 URL 값은 필수 입니다.
|
|
||||||
context.buildConstraintViolationWithTemplate(messageUtil.getMessage("reserve_item.external_url")+ messageUtil.getMessage("valid.required"))
|
|
||||||
.addPropertyNode("externalUrl")
|
|
||||||
.addConstraintViolation();
|
|
||||||
fieldValid = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if ("telephone".equals(reserveMethodId)) {
|
|
||||||
//예약 방법인 '전화'인 경우 contact 필수
|
|
||||||
if (isNull(value, "contact")) {
|
|
||||||
context.disableDefaultConstraintViolation();
|
|
||||||
//문의처 값은 필수입니다.
|
|
||||||
context.buildConstraintViolationWithTemplate(messageUtil.getMessage("reserve_item.contact")+ messageUtil.getMessage("valid.required"))
|
|
||||||
.addPropertyNode("contact")
|
|
||||||
.addConstraintViolation();
|
|
||||||
fieldValid = false;
|
|
||||||
}
|
|
||||||
}else if ("visit".equals(reserveMethodId)) {
|
|
||||||
//예약 방법인 '방문'인 경우 주소 필수
|
|
||||||
if (isNull(value, "address")) {
|
|
||||||
context.disableDefaultConstraintViolation();
|
|
||||||
//주소 값은 필수 입니다.
|
|
||||||
context.buildConstraintViolationWithTemplate(messageUtil.getMessage("common.address")+ messageUtil.getMessage("valid.required"))
|
|
||||||
.addPropertyNode("address")
|
|
||||||
.addConstraintViolation();
|
|
||||||
fieldValid = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 유료인 경우 이용 요금 필수
|
return fieldValid;
|
||||||
Boolean isPaid = Boolean.valueOf(String.valueOf(getFieldValue(value, "isPaid")));
|
}
|
||||||
if (isPaid && isNull(value, "usageCost")) {
|
|
||||||
|
/**
|
||||||
|
* 예약 신청 일자 정합성 체크
|
||||||
|
*
|
||||||
|
* @param value
|
||||||
|
* @param context
|
||||||
|
* @throws NoSuchFieldException
|
||||||
|
* @throws IllegalAccessException
|
||||||
|
*/
|
||||||
|
private boolean validateRequestDate(Object value, ConstraintValidatorContext context)
|
||||||
|
throws NoSuchFieldException, IllegalAccessException {
|
||||||
|
|
||||||
|
if (isNull(value, "requestStartDate")) {
|
||||||
context.disableDefaultConstraintViolation();
|
context.disableDefaultConstraintViolation();
|
||||||
//이용요금 값은 필수입니다.
|
// 예약 신청 시작일 값은 필수 입니다.
|
||||||
context.buildConstraintViolationWithTemplate(messageUtil.getMessage("reserve_item.usage_fee")+ messageUtil.getMessage("valid.required"))
|
context.buildConstraintViolationWithTemplate(
|
||||||
.addPropertyNode("usageCost")
|
messageUtil.getMessage("reserve_item.request") + " " + messageUtil
|
||||||
|
.getMessage("common.start_datetime") + messageUtil.getMessage("valid.required"))
|
||||||
|
.addPropertyNode("requestStartDate")
|
||||||
.addConstraintViolation();
|
.addConstraintViolation();
|
||||||
fieldValid = false;
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isNull(value, "requestEndDate")) {
|
||||||
|
context.disableDefaultConstraintViolation();
|
||||||
|
// 예약 신청 종료일 값은 필수 입니다.
|
||||||
|
context.buildConstraintViolationWithTemplate(
|
||||||
|
messageUtil.getMessage("reserve_item.request") + " " + messageUtil
|
||||||
|
.getMessage("common.end_datetime") + messageUtil.getMessage("valid.required"))
|
||||||
|
.addPropertyNode("requestEndDate")
|
||||||
|
.addConstraintViolation();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
LocalDateTime requestStartDate = (LocalDateTime) getFieldValue(value, "requestStartDate");
|
||||||
|
LocalDateTime requestEndDate = (LocalDateTime) getFieldValue(value, "requestEndDate");
|
||||||
|
if (requestStartDate.isAfter(requestEndDate)) {
|
||||||
|
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("requestStartDate")
|
||||||
|
.addConstraintViolation();
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return fieldValid;
|
return fieldValid;
|
||||||
@@ -190,7 +343,8 @@ public class ReserveItemSaveValidator implements ConstraintValidator<ReserveItem
|
|||||||
* @throws NoSuchFieldException
|
* @throws NoSuchFieldException
|
||||||
* @throws IllegalAccessException
|
* @throws IllegalAccessException
|
||||||
*/
|
*/
|
||||||
private Object getFieldValue(Object object, String fieldName) throws NoSuchFieldException, IllegalAccessException {
|
private Object getFieldValue(Object object, String fieldName)
|
||||||
|
throws NoSuchFieldException, IllegalAccessException {
|
||||||
Class<?> clazz = object.getClass();
|
Class<?> clazz = object.getClass();
|
||||||
Field field = clazz.getDeclaredField(fieldName);
|
Field field = clazz.getDeclaredField(fieldName);
|
||||||
field.setAccessible(true);
|
field.setAccessible(true);
|
||||||
@@ -206,10 +360,12 @@ public class ReserveItemSaveValidator implements ConstraintValidator<ReserveItem
|
|||||||
* @throws NoSuchFieldException
|
* @throws NoSuchFieldException
|
||||||
* @throws IllegalAccessException
|
* @throws IllegalAccessException
|
||||||
*/
|
*/
|
||||||
private boolean isNull(Object object, String fieldName) throws NoSuchFieldException, IllegalAccessException {
|
private boolean isNull(Object object, String fieldName)
|
||||||
|
throws NoSuchFieldException, IllegalAccessException {
|
||||||
Class<?> clazz = object.getClass();
|
Class<?> clazz = object.getClass();
|
||||||
Field field = clazz.getDeclaredField(fieldName);
|
Field field = clazz.getDeclaredField(fieldName);
|
||||||
field.setAccessible(true);
|
field.setAccessible(true);
|
||||||
return field.get(object) == null || !StringUtils.hasLength(String.valueOf(field.get(object)));
|
return field.get(object) == null || !StringUtils
|
||||||
|
.hasLength(String.valueOf(field.get(object)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,12 @@
|
|||||||
package org.egovframe.cloud.reserveitemservice.validator.annotation;
|
package org.egovframe.cloud.reserveitemservice.validator.annotation;
|
||||||
|
|
||||||
import org.egovframe.cloud.reserveitemservice.validator.ReserveItemSaveValidator;
|
|
||||||
|
|
||||||
import javax.validation.Constraint;
|
|
||||||
import javax.validation.Payload;
|
|
||||||
import java.lang.annotation.ElementType;
|
import java.lang.annotation.ElementType;
|
||||||
import java.lang.annotation.Retention;
|
import java.lang.annotation.Retention;
|
||||||
import java.lang.annotation.RetentionPolicy;
|
import java.lang.annotation.RetentionPolicy;
|
||||||
import java.lang.annotation.Target;
|
import java.lang.annotation.Target;
|
||||||
|
import javax.validation.Constraint;
|
||||||
|
import javax.validation.Payload;
|
||||||
|
import org.egovframe.cloud.reserveitemservice.validator.ReserveItemSaveValidator;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* org.egovframe.cloud.reserveitemservice.validator.annotation.ReserveItemSaveValid
|
* org.egovframe.cloud.reserveitemservice.validator.annotation.ReserveItemSaveValid
|
||||||
|
|||||||
@@ -108,7 +108,7 @@ class ReserveItemApiControllerTest {
|
|||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void 사용자목록조회_성공() throws Exception {
|
public void 사용자목록조회_성공() {
|
||||||
|
|
||||||
ReserveItem saved = reserveItemRepository.save(reserveItem).block();
|
ReserveItem saved = reserveItemRepository.save(reserveItem).block();
|
||||||
assertNotNull(saved);
|
assertNotNull(saved);
|
||||||
@@ -123,7 +123,7 @@ class ReserveItemApiControllerTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void 관리자목록조회_성공() throws Exception {
|
public void 관리자목록조회_성공() {
|
||||||
|
|
||||||
ReserveItem saved = reserveItemRepository.save(reserveItem).block();
|
ReserveItem saved = reserveItemRepository.save(reserveItem).block();
|
||||||
assertNotNull(saved);
|
assertNotNull(saved);
|
||||||
@@ -138,7 +138,7 @@ class ReserveItemApiControllerTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void 한건조회_성공() throws Exception {
|
public void 한건조회_성공() {
|
||||||
ReserveItem saved = reserveItemRepository.save(reserveItem).block();
|
ReserveItem saved = reserveItemRepository.save(reserveItem).block();
|
||||||
assertNotNull(saved);
|
assertNotNull(saved);
|
||||||
|
|
||||||
@@ -155,7 +155,7 @@ class ReserveItemApiControllerTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void 사용자_포털_메인_예약목록_조회_성공() throws Exception {
|
public void 사용자_포털_메인_예약목록_조회_성공() {
|
||||||
ReserveItem saved = reserveItemRepository.save(reserveItem).block();
|
ReserveItem saved = reserveItemRepository.save(reserveItem).block();
|
||||||
assertNotNull(saved);
|
assertNotNull(saved);
|
||||||
|
|
||||||
@@ -176,7 +176,7 @@ class ReserveItemApiControllerTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void 한건_등록_성공() throws Exception {
|
public void 한건_등록_성공() {
|
||||||
ReserveItemSaveRequestDto requestDto = ReserveItemSaveRequestDto.builder()
|
ReserveItemSaveRequestDto requestDto = ReserveItemSaveRequestDto.builder()
|
||||||
.reserveItemName(reserveItem.getReserveItemName())
|
.reserveItemName(reserveItem.getReserveItemName())
|
||||||
.categoryId(reserveItem.getCategoryId())
|
.categoryId(reserveItem.getCategoryId())
|
||||||
@@ -208,7 +208,7 @@ class ReserveItemApiControllerTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void 한건_수정_성공() throws Exception {
|
public void 한건_수정_성공() {
|
||||||
ReserveItem saved = reserveItemRepository.save(reserveItem).block();
|
ReserveItem saved = reserveItemRepository.save(reserveItem).block();
|
||||||
assertNotNull(saved);
|
assertNotNull(saved);
|
||||||
|
|
||||||
@@ -241,7 +241,7 @@ class ReserveItemApiControllerTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void 사용여부_false_수정_성공() throws Exception {
|
public void 사용여부_false_수정_성공() {
|
||||||
ReserveItem saved = reserveItemRepository.save(reserveItem).block();
|
ReserveItem saved = reserveItemRepository.save(reserveItem).block();
|
||||||
assertNotNull(saved);
|
assertNotNull(saved);
|
||||||
|
|
||||||
@@ -255,7 +255,7 @@ class ReserveItemApiControllerTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void 한건_저장_validation_실패() throws Exception {
|
public void 한건_저장_validation_실패() {
|
||||||
ReserveItemSaveRequestDto requestDto = ReserveItemSaveRequestDto.builder()
|
ReserveItemSaveRequestDto requestDto = ReserveItemSaveRequestDto.builder()
|
||||||
.reserveItemName(reserveItem.getReserveItemName())
|
.reserveItemName(reserveItem.getReserveItemName())
|
||||||
.categoryId(reserveItem.getCategoryId())
|
.categoryId(reserveItem.getCategoryId())
|
||||||
@@ -271,6 +271,8 @@ class ReserveItemApiControllerTest {
|
|||||||
.selectionMeansId(reserveItem.getSelectionMeansId())
|
.selectionMeansId(reserveItem.getSelectionMeansId())
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
|
System.out.println(requestDto);
|
||||||
|
|
||||||
ErrorResponse responseBody = webTestClient.post()
|
ErrorResponse responseBody = webTestClient.post()
|
||||||
.uri(API_URL)
|
.uri(API_URL)
|
||||||
.bodyValue(requestDto)
|
.bodyValue(requestDto)
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
package org.egovframe.cloud.reserverequestservice.api.dto;
|
package org.egovframe.cloud.reserverequestservice.api.dto;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
import lombok.*;
|
import lombok.*;
|
||||||
import org.egovframe.cloud.reserverequestservice.domain.Reserve;
|
import org.egovframe.cloud.reserverequestservice.domain.Reserve;
|
||||||
|
|
||||||
import javax.validation.constraints.NotNull;
|
import javax.validation.constraints.NotNull;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
|
import org.egovframe.cloud.reserverequestservice.domain.ReserveStatus;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* org.egovframe.cloud.reserverequestservice.api.dto.ReserveSaveRequestDto
|
* org.egovframe.cloud.reserverequestservice.api.dto.ReserveSaveRequestDto
|
||||||
@@ -90,6 +92,18 @@ public class ReserveSaveRequestDto {
|
|||||||
this.userEmail = userEmail;
|
this.userEmail = userEmail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Reserve createRequestReserve() {
|
||||||
|
this.reserveId = String.valueOf(UUID.randomUUID());
|
||||||
|
this.reserveStatusId = ReserveStatus.REQUEST.getKey();
|
||||||
|
return toEntity();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Reserve createApproveReserve() {
|
||||||
|
this.reserveId = String.valueOf(UUID.randomUUID());
|
||||||
|
this.reserveStatusId = ReserveStatus.APPROVE.getKey();
|
||||||
|
return toEntity();
|
||||||
|
}
|
||||||
|
|
||||||
public Reserve toEntity() {
|
public Reserve toEntity() {
|
||||||
return Reserve.builder()
|
return Reserve.builder()
|
||||||
.reserveId(this.reserveId)
|
.reserveId(this.reserveId)
|
||||||
|
|||||||
@@ -0,0 +1,176 @@
|
|||||||
|
package org.egovframe.cloud.reserverequestservice.domain;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.temporal.ChronoUnit;
|
||||||
|
import java.util.stream.IntStream;
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.egovframe.cloud.common.exception.BusinessMessageException;
|
||||||
|
import org.egovframe.cloud.common.util.MessageUtil;
|
||||||
|
import org.egovframe.cloud.reserverequestservice.api.dto.ReserveSaveRequestDto;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import reactor.core.publisher.Flux;
|
||||||
|
import reactor.core.publisher.Mono;
|
||||||
|
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
@Component
|
||||||
|
public class ReserveValidator {
|
||||||
|
|
||||||
|
@Resource(
|
||||||
|
name = "messageUtil"
|
||||||
|
)
|
||||||
|
protected MessageUtil messageUtil;
|
||||||
|
|
||||||
|
private final ReserveRepository reserveRepository;
|
||||||
|
|
||||||
|
public Mono<ReserveSaveRequestDto> checkValidation(ReserveSaveRequestDto saveRequestDto) {
|
||||||
|
if (Category.EQUIPMENT.isEquals(saveRequestDto.getCategoryId())) {
|
||||||
|
return checkEquipment(saveRequestDto);
|
||||||
|
}else if (Category.SPACE.isEquals(saveRequestDto.getCategoryId())) {
|
||||||
|
return checkSpace(saveRequestDto);
|
||||||
|
}
|
||||||
|
//해당 날짜에는 예약할 수 없습니다.
|
||||||
|
return Mono.error(new BusinessMessageException(getMessage("valid.reserve_date")));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 예약 날자 validation
|
||||||
|
*
|
||||||
|
* @param saveRequestDto
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public Mono<ReserveSaveRequestDto> checkReserveDate(ReserveSaveRequestDto saveRequestDto) {
|
||||||
|
LocalDateTime startDate = saveRequestDto.getReserveMeansId().equals("realtime") ?
|
||||||
|
saveRequestDto.getRequestStartDate() : saveRequestDto.getOperationStartDate();
|
||||||
|
LocalDateTime endDate = saveRequestDto.getReserveMeansId().equals("realtime") ?
|
||||||
|
saveRequestDto.getRequestEndDate() : saveRequestDto.getOperationEndDate();
|
||||||
|
|
||||||
|
if (saveRequestDto.getReserveStartDate().isBefore(startDate)) {
|
||||||
|
//{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 (saveRequestDto.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 (saveRequestDto.getIsPeriod()) {
|
||||||
|
long between = ChronoUnit.DAYS.between(saveRequestDto.getReserveStartDate(),
|
||||||
|
saveRequestDto.getReserveEndDate());
|
||||||
|
if (saveRequestDto.getPeriodMaxCount() < between) {
|
||||||
|
//최대 예약 가능 일수보다 예약기간이 깁니다. (최대 예약 가능일 수 : {0})
|
||||||
|
return Mono.error(new BusinessMessageException(getMessage("valid.reserve_period", new Object[]{saveRequestDto.getPeriodMaxCount()})));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Mono.just(saveRequestDto);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 공간 예약 시 예약 날짜에 다른 예약이 있는지 체크
|
||||||
|
*
|
||||||
|
* @param saveRequestDto
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public Mono<ReserveSaveRequestDto> checkSpace(ReserveSaveRequestDto saveRequestDto) {
|
||||||
|
return this.checkReserveDate(saveRequestDto)
|
||||||
|
.flatMap(result -> reserveRepository.findAllByReserveDateCount(
|
||||||
|
result.getReserveItemId(),
|
||||||
|
result.getReserveStartDate(),
|
||||||
|
result.getReserveEndDate())
|
||||||
|
.flatMap(count -> {
|
||||||
|
if (count > 0) {
|
||||||
|
//해당 날짜에는 예약할 수 없습니다.
|
||||||
|
return Mono.error(new BusinessMessageException(getMessage("valid.reserve_date")));
|
||||||
|
}
|
||||||
|
return Mono.just(result);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 장비 예약 시 예약 날짜에 예약 가능한 재고 체크
|
||||||
|
*
|
||||||
|
* @param saveRequestDto
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public Mono<ReserveSaveRequestDto> checkEquipment(ReserveSaveRequestDto saveRequestDto) {
|
||||||
|
return this.checkReserveDate(saveRequestDto)
|
||||||
|
.flatMap(result -> this.getMaxByReserveDate(
|
||||||
|
result.getReserveItemId(),
|
||||||
|
result.getReserveStartDate(),
|
||||||
|
result.getReserveEndDate())
|
||||||
|
.flatMap(max -> {
|
||||||
|
if ((result.getTotalQty() - max) < result.getReserveQty()) {
|
||||||
|
return Mono.just(false);
|
||||||
|
}
|
||||||
|
return Mono.just(true);
|
||||||
|
})
|
||||||
|
.flatMap(isValid -> {
|
||||||
|
if (!isValid) {
|
||||||
|
//해당 날짜에 예약할 수 있는 재고수량이 없습니다.
|
||||||
|
return Mono.error(new BusinessMessageException(getMessage("valid.reserve_count")));
|
||||||
|
}
|
||||||
|
return Mono.just(saveRequestDto);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 예약물품에 대해 날짜별 예약된 수량 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());
|
||||||
|
|
||||||
|
if (reserveFlux.equals(Flux.empty())) {
|
||||||
|
return Mono.just(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
long between = ChronoUnit.DAYS.between(startDate, endDate);
|
||||||
|
|
||||||
|
if (between == 0) {
|
||||||
|
return reserveFlux.map(reserve -> {
|
||||||
|
if (startDate.isAfter(reserve.getReserveStartDate())
|
||||||
|
|| startDate.isBefore(reserve.getReserveEndDate())
|
||||||
|
|| startDate.isEqual(reserve.getReserveStartDate()) || startDate.isEqual(reserve.getReserveEndDate())) {
|
||||||
|
return reserve.getReserveQty();
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}).reduce(0, (x1, x2) -> x1 + x2);
|
||||||
|
}
|
||||||
|
|
||||||
|
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())
|
||||||
|
|| localDateTime.isEqual(findReserve.getReserveStartDate()) || localDateTime.isEqual(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);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getMessage(String code) {
|
||||||
|
return this.messageUtil.getMessage(code);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getMessage(String code, Object[] args) {
|
||||||
|
return this.messageUtil.getMessage(code, args);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
package org.egovframe.cloud.reserverequestservice.service;
|
package org.egovframe.cloud.reserverequestservice.service;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.egovframe.cloud.common.config.GlobalConstant;
|
import org.egovframe.cloud.common.config.GlobalConstant;
|
||||||
@@ -12,23 +13,23 @@ import org.egovframe.cloud.reserverequestservice.domain.Category;
|
|||||||
import org.egovframe.cloud.reserverequestservice.domain.Reserve;
|
import org.egovframe.cloud.reserverequestservice.domain.Reserve;
|
||||||
import org.egovframe.cloud.reserverequestservice.domain.ReserveRepository;
|
import org.egovframe.cloud.reserverequestservice.domain.ReserveRepository;
|
||||||
import org.egovframe.cloud.reserverequestservice.domain.ReserveStatus;
|
import org.egovframe.cloud.reserverequestservice.domain.ReserveStatus;
|
||||||
import org.springframework.amqp.core.*;
|
import org.egovframe.cloud.reserverequestservice.domain.ReserveValidator;
|
||||||
|
import org.springframework.amqp.core.AmqpAdmin;
|
||||||
|
import org.springframework.amqp.core.Binding;
|
||||||
|
import org.springframework.amqp.core.BindingBuilder;
|
||||||
|
import org.springframework.amqp.core.Exchange;
|
||||||
|
import org.springframework.amqp.core.ExchangeBuilder;
|
||||||
|
import org.springframework.amqp.core.Queue;
|
||||||
|
import org.springframework.amqp.core.QueueBuilder;
|
||||||
import org.springframework.cloud.stream.function.StreamBridge;
|
import org.springframework.cloud.stream.function.StreamBridge;
|
||||||
import org.springframework.security.core.Authentication;
|
import org.springframework.security.core.Authentication;
|
||||||
import org.springframework.security.core.context.ReactiveSecurityContextHolder;
|
import org.springframework.security.core.context.ReactiveSecurityContextHolder;
|
||||||
import org.springframework.security.core.context.SecurityContext;
|
import org.springframework.security.core.context.SecurityContext;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
import reactor.core.publisher.Flux;
|
|
||||||
import reactor.core.publisher.Mono;
|
import reactor.core.publisher.Mono;
|
||||||
import reactor.core.scheduler.Schedulers;
|
import reactor.core.scheduler.Schedulers;
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
|
||||||
import java.time.temporal.ChronoUnit;
|
|
||||||
import java.util.UUID;
|
|
||||||
import java.util.stream.IntStream;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* org.egovframe.cloud.reserverequestservice.service.ReserveService
|
* org.egovframe.cloud.reserverequestservice.service.ReserveService
|
||||||
* <p>
|
* <p>
|
||||||
@@ -52,33 +53,10 @@ import java.util.stream.IntStream;
|
|||||||
@Service
|
@Service
|
||||||
public class ReserveService extends ReactiveAbstractService {
|
public class ReserveService extends ReactiveAbstractService {
|
||||||
private final ReserveRepository reserveRepository;
|
private final ReserveRepository reserveRepository;
|
||||||
|
private final ReserveValidator reserveValidator;
|
||||||
private final StreamBridge streamBridge;
|
private final StreamBridge streamBridge;
|
||||||
private final AmqpAdmin amqpAdmin;
|
private final AmqpAdmin amqpAdmin;
|
||||||
|
|
||||||
/**
|
|
||||||
* entity -> dto 변환
|
|
||||||
*
|
|
||||||
* @param reserve
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
private Mono<ReserveResponseDto> convertReserveResponseDto(Reserve reserve) {
|
|
||||||
return Mono.just(ReserveResponseDto.builder()
|
|
||||||
.entity(reserve)
|
|
||||||
.build());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 현재 로그인 사용자 id
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
private Mono<String> getUserId() {
|
|
||||||
return ReactiveSecurityContextHolder.getContext()
|
|
||||||
.map(SecurityContext::getAuthentication)
|
|
||||||
.filter(Authentication::isAuthenticated)
|
|
||||||
.map(Authentication::getPrincipal)
|
|
||||||
.map(String.class::cast);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 예약 신청 저장
|
* 예약 신청 저장
|
||||||
@@ -88,12 +66,7 @@ public class ReserveService extends ReactiveAbstractService {
|
|||||||
*/
|
*/
|
||||||
public Mono<ReserveResponseDto> create(ReserveSaveRequestDto saveRequestDto) {
|
public Mono<ReserveResponseDto> create(ReserveSaveRequestDto saveRequestDto) {
|
||||||
return Mono.just(saveRequestDto)
|
return Mono.just(saveRequestDto)
|
||||||
.flatMap(dto -> {
|
.flatMap(dto -> Mono.just(dto.createRequestReserve()))
|
||||||
String uuid = UUID.randomUUID().toString();
|
|
||||||
dto.setReserveId(uuid);
|
|
||||||
dto.setReserveStatusId(ReserveStatus.REQUEST.getKey());
|
|
||||||
return Mono.just(dto.toEntity());
|
|
||||||
})
|
|
||||||
.zipWith(getUserId())
|
.zipWith(getUserId())
|
||||||
.flatMap(tuple -> {
|
.flatMap(tuple -> {
|
||||||
tuple.getT1().setCreatedInfo(LocalDateTime.now(), tuple.getT2());
|
tuple.getT1().setCreatedInfo(LocalDateTime.now(), tuple.getT2());
|
||||||
@@ -152,162 +125,14 @@ public class ReserveService extends ReactiveAbstractService {
|
|||||||
*/
|
*/
|
||||||
public Mono<ReserveResponseDto> save(ReserveSaveRequestDto saveRequestDto) {
|
public Mono<ReserveResponseDto> save(ReserveSaveRequestDto saveRequestDto) {
|
||||||
return Mono.just(saveRequestDto)
|
return Mono.just(saveRequestDto)
|
||||||
.flatMap(this::checkValidation)
|
.flatMap(this::validate)
|
||||||
.onErrorResume(throwable -> Mono.error(throwable))
|
.onErrorResume(throwable -> Mono.error(throwable))
|
||||||
.flatMap(dto -> {
|
.flatMap(dto -> Mono.just(dto.createApproveReserve())).zipWith(getUserId())
|
||||||
String uuid = UUID.randomUUID().toString();
|
|
||||||
dto.setReserveId(uuid);
|
|
||||||
dto.setReserveStatusId(ReserveStatus.APPROVE.getKey());
|
|
||||||
return Mono.just(dto.toEntity());
|
|
||||||
}).zipWith(getUserId())
|
|
||||||
.flatMap(tuple -> Mono.just(tuple.getT1().setCreatedInfo(LocalDateTime.now(), tuple.getT2())))
|
.flatMap(tuple -> Mono.just(tuple.getT1().setCreatedInfo(LocalDateTime.now(), tuple.getT2())))
|
||||||
.flatMap(reserveRepository::insert)
|
.flatMap(reserveRepository::insert)
|
||||||
.flatMap(this::convertReserveResponseDto);
|
.flatMap(this::convertReserveResponseDto);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Mono<ReserveSaveRequestDto> checkValidation(ReserveSaveRequestDto saveRequestDto) {
|
|
||||||
if (Category.EQUIPMENT.isEquals(saveRequestDto.getCategoryId())) {
|
|
||||||
return checkEquipment(saveRequestDto);
|
|
||||||
}else if (Category.SPACE.isEquals(saveRequestDto.getCategoryId())) {
|
|
||||||
return checkSpace(saveRequestDto);
|
|
||||||
}
|
|
||||||
//해당 날짜에는 예약할 수 없습니다.
|
|
||||||
return Mono.error(new BusinessMessageException(getMessage("valid.reserve_date")));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 예약 날자 validation
|
|
||||||
*
|
|
||||||
* @param saveRequestDto
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
private Mono<ReserveSaveRequestDto> checkReserveDate(ReserveSaveRequestDto saveRequestDto) {
|
|
||||||
LocalDateTime startDate = saveRequestDto.getReserveMeansId().equals("realtime") ?
|
|
||||||
saveRequestDto.getRequestStartDate() : saveRequestDto.getOperationStartDate();
|
|
||||||
LocalDateTime endDate = saveRequestDto.getReserveMeansId().equals("realtime") ?
|
|
||||||
saveRequestDto.getRequestEndDate() : saveRequestDto.getOperationEndDate();
|
|
||||||
|
|
||||||
if (saveRequestDto.getReserveStartDate().isBefore(startDate)) {
|
|
||||||
//{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 (saveRequestDto.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 (saveRequestDto.getIsPeriod()) {
|
|
||||||
long between = ChronoUnit.DAYS.between(saveRequestDto.getReserveStartDate(),
|
|
||||||
saveRequestDto.getReserveEndDate());
|
|
||||||
if (saveRequestDto.getPeriodMaxCount() < between) {
|
|
||||||
//최대 예약 가능 일수보다 예약기간이 깁니다. (최대 예약 가능일 수 : {0})
|
|
||||||
return Mono.error(new BusinessMessageException(getMessage("valid.reserve_period", new Object[]{saveRequestDto.getPeriodMaxCount()})));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Mono.just(saveRequestDto);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 공간 예약 시 예약 날짜에 다른 예약이 있는지 체크
|
|
||||||
*
|
|
||||||
* @param saveRequestDto
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
private Mono<ReserveSaveRequestDto> checkSpace(ReserveSaveRequestDto saveRequestDto) {
|
|
||||||
return this.checkReserveDate(saveRequestDto)
|
|
||||||
.flatMap(result -> reserveRepository.findAllByReserveDateCount(
|
|
||||||
result.getReserveItemId(),
|
|
||||||
result.getReserveStartDate(),
|
|
||||||
result.getReserveEndDate())
|
|
||||||
.flatMap(count -> {
|
|
||||||
if (count > 0) {
|
|
||||||
//해당 날짜에는 예약할 수 없습니다.
|
|
||||||
return Mono.error(new BusinessMessageException(getMessage("valid.reserve_date")));
|
|
||||||
}
|
|
||||||
return Mono.just(result);
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 장비 예약 시 예약 날짜에 예약 가능한 재고 체크
|
|
||||||
*
|
|
||||||
* @param saveRequestDto
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
private Mono<ReserveSaveRequestDto> checkEquipment(ReserveSaveRequestDto saveRequestDto) {
|
|
||||||
return this.checkReserveDate(saveRequestDto)
|
|
||||||
.flatMap(result -> this.getMaxByReserveDate(
|
|
||||||
result.getReserveItemId(),
|
|
||||||
result.getReserveStartDate(),
|
|
||||||
result.getReserveEndDate())
|
|
||||||
.flatMap(max -> {
|
|
||||||
if ((result.getTotalQty() - max) < result.getReserveQty()) {
|
|
||||||
return Mono.just(false);
|
|
||||||
}
|
|
||||||
return Mono.just(true);
|
|
||||||
})
|
|
||||||
.flatMap(isValid -> {
|
|
||||||
if (!isValid) {
|
|
||||||
//해당 날짜에 예약할 수 있는 재고수량이 없습니다.
|
|
||||||
return Mono.error(new BusinessMessageException(getMessage("valid.reserve_count")));
|
|
||||||
}
|
|
||||||
return Mono.just(saveRequestDto);
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 예약물품에 대해 날짜별 예약된 수량 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());
|
|
||||||
|
|
||||||
if (reserveFlux.equals(Flux.empty())) {
|
|
||||||
return Mono.just(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
long between = ChronoUnit.DAYS.between(startDate, endDate);
|
|
||||||
|
|
||||||
if (between == 0) {
|
|
||||||
return reserveFlux.map(reserve -> {
|
|
||||||
if (startDate.isAfter(reserve.getReserveStartDate())
|
|
||||||
|| startDate.isBefore(reserve.getReserveEndDate())
|
|
||||||
|| startDate.isEqual(reserve.getReserveStartDate()) || startDate.isEqual(reserve.getReserveEndDate())) {
|
|
||||||
return reserve.getReserveQty();
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}).reduce(0, (x1, x2) -> x1 + x2);
|
|
||||||
}
|
|
||||||
|
|
||||||
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())
|
|
||||||
|| localDateTime.isEqual(findReserve.getReserveStartDate()) || localDateTime.isEqual(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);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 예약 신청 후 예약 물품 재고 변경 성공 시 예약승인으로 상태 변경
|
* 예약 신청 후 예약 물품 재고 변경 성공 시 예약승인으로 상태 변경
|
||||||
*
|
*
|
||||||
@@ -336,4 +161,47 @@ public class ReserveService extends ReactiveAbstractService {
|
|||||||
.then();
|
.then();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* entity -> dto 변환
|
||||||
|
*
|
||||||
|
* @param reserve
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private Mono<ReserveResponseDto> convertReserveResponseDto(Reserve reserve) {
|
||||||
|
return Mono.just(ReserveResponseDto.builder()
|
||||||
|
.entity(reserve)
|
||||||
|
.build());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 현재 로그인 사용자 id
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private Mono<String> getUserId() {
|
||||||
|
return ReactiveSecurityContextHolder.getContext()
|
||||||
|
.map(SecurityContext::getAuthentication)
|
||||||
|
.filter(Authentication::isAuthenticated)
|
||||||
|
.map(Authentication::getPrincipal)
|
||||||
|
.map(String.class::cast);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 저장 시 정합성 체크
|
||||||
|
*
|
||||||
|
* @param saveRequestDto
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private Mono<ReserveSaveRequestDto> validate(ReserveSaveRequestDto saveRequestDto) {
|
||||||
|
if (Category.EQUIPMENT.isEquals(saveRequestDto.getCategoryId())) {
|
||||||
|
return reserveValidator.checkEquipment(saveRequestDto);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Category.SPACE.isEquals(saveRequestDto.getCategoryId())) {
|
||||||
|
return reserveValidator.checkSpace(saveRequestDto);
|
||||||
|
}
|
||||||
|
//해당 날짜에는 예약할 수 없습니다.
|
||||||
|
return Mono.error(new BusinessMessageException(getMessage("valid.reserve_date")));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ class ReserveApiControllerTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
@WithCustomMockUser(userId = "user", role = Role.USER)
|
@WithCustomMockUser(userId = "user", role = Role.USER)
|
||||||
public void 사용자_예약_성공() throws Exception {
|
public void 사용자_예약_성공() {
|
||||||
|
|
||||||
ReserveSaveRequestDto saveRequestDto =
|
ReserveSaveRequestDto saveRequestDto =
|
||||||
ReserveSaveRequestDto.builder()
|
ReserveSaveRequestDto.builder()
|
||||||
|
|||||||
Reference in New Issue
Block a user