728x90
반응형
기존 로직
@Service
@RequiredArgsConstructor
public class test {
private final ProductRepository productRepository;
private final ProductInfoPerNightRepository productInfoPerNightRepository;
private final AccommodationRepository accommodationRepository;
@Transactional(readOnly = true)
public AccommodationDetailListResponse getAccommodationDetail(
Long accommodationId, LocalDate checkInDate,
LocalDate checkOutDate, int personNumber) {
validateInputs(checkInDate, checkOutDate, personNumber);
Accommodation accommodationEntity = accommodationRepository.findById(accommodationId)
.orElseThrow(() -> new AccommodationException(ErrorType.NOT_FOUND));
List<Product> productEntityList = productRepository.findAllByAccommodationId(
accommodationId);
List<ProductInfoPerNight> productInfoPerNightList = productInfoPerNightRepository
.findByAccommodationIdAndDateRange(accommodationId, checkInDate, checkOutDate);
Map<Long, List<ProductInfoPerNight>> productInfoPerNightsMap = productInfoPerNightList.stream()
.collect(Collectors.groupingBy(p -> p.getProduct().getId()));
List<Product> validProductList = productEntityList.stream()
.filter(product -> {
List<ProductInfoPerNight> infoPerNights = productInfoPerNightsMap.get(product.getId());
if (infoPerNights == null || infoPerNights.size() < ChronoUnit.DAYS.between(checkInDate, checkOutDate)) {
return false;
}
return personNumber <= product.getMaximumNumber();
})
.collect(Collectors.toList());
if (validProductList.isEmpty()) {
throw new ProductException(ErrorType.INVALID_NUMBER_OF_PEOPLE);
}
List<ProductResponse> productResponses = validProductList.stream()
.map(product -> {
ProductImageResponse productImageResponse = ProductImageResponse.from(product.getProductImage());
int minCount = productInfoPerNightsMap.get(product.getId()).stream()
.mapToInt(ProductInfoPerNight::getCount)
.min()
.orElse(0);
return ProductResponse.from(product, minCount, productImageResponse);
})
.collect(Collectors.toList());
AccommodationImageResponse accommodationImageResponse = AccommodationImageResponse
.from(accommodationEntity.getImages());
AccommodationOptionResponse accommodationOptionResponse = AccommodationOptionResponse
.from(accommodationEntity.getOptions());
return AccommodationDetailListResponse.from(accommodationEntity, checkInDate,
checkOutDate, accommodationImageResponse,
accommodationOptionResponse, productResponses);
}
@Transactional(readOnly = true)
public ProductDetailResponse getProductDetail(
Long accommodationId, Long productId,
LocalDate checkInDate, LocalDate checkOutDate,
int personNumber) {
validateInputs(checkInDate, checkOutDate, personNumber);
Accommodation accommodationEntity = accommodationRepository.findById(accommodationId)
.orElseThrow(() -> new AccommodationException(ErrorType.NOT_FOUND));
Product productEntity = productRepository.findByIdAndAccommodationId(productId, accommodationId)
.orElseThrow(() -> new ProductException(ErrorType.NOT_FOUND));
if (personNumber > productEntity.getMaximumNumber()) {
throw new ProductException(ErrorType.INVALID_NUMBER_OF_PEOPLE);
}
List<ProductInfoPerNight> availableProductPerNights = productInfoPerNightRepository
.findByProductIdAndDateRange(productId, checkInDate, checkOutDate);
long expectedNights = ChronoUnit.DAYS.between(checkInDate, checkOutDate);
if (availableProductPerNights.size() < expectedNights) {
throw new ProductException(ErrorType.NOT_FOUND);
}
int totalPrice = availableProductPerNights.stream()
.mapToInt(ProductInfoPerNight::getPrice)
.sum();
ProductImageResponse productImageResponse = ProductImageResponse.from(
productEntity.getProductImage());
ProductOptionResponse productOptionResponse = ProductOptionResponse.from(
productEntity.getProductOption());
return ProductDetailResponse.from(productEntity, accommodationEntity.getName(),
availableProductPerNights.get(0).getPrice(), totalPrice, (int) expectedNights,
productImageResponse, productOptionResponse);
}
private void validateInputs(LocalDate checkInDate, LocalDate checkOutDate,
int personNumber) {
if (!isCheckInValid(checkInDate)) {
throw new AccommodationException(ErrorType.INVALID_CHECK_IN);
}
if (!isCheckOutValid(checkInDate, checkOutDate)) {
throw new AccommodationException(ErrorType.INVALID_CHECK_OUT);
}
if (personNumber < 1) {
throw new AccommodationException(ErrorType.INVALID_NUMBER_OF_PEOPLE);
}
}
분리된 로직
@Service
@RequiredArgsConstructor
public class ProductService {
private final ProductRepository productRepository;
private final ProductInfoPerNightRepository productInfoPerNightRepository;
private final AccommodationRepository accommodationRepository;
@Transactional(readOnly = true)
public AccommodationDetailListResponse getAccommodationDetail(
Long accommodationId, LocalDate checkInDate,
LocalDate checkOutDate, int personNumber) {
validateInputs(checkInDate, checkOutDate, personNumber);
Accommodation accommodationEntity = findAccommodation(accommodationId);
List<Product> productEntityList = productRepository.findAllByAccommodationId(
accommodationId);
List<ProductInfoPerNight> productInfoPerNightList = productInfoPerNightRepository
.findByAccommodationIdAndDateRange(accommodationId, checkInDate, checkOutDate);
List<Product> validProductList = findProductList(productEntityList, productInfoPerNightList,
checkInDate, checkOutDate, personNumber);
if (validProductList.isEmpty()) {
throw new ProductException(ErrorType.INVALID_NUMBER_OF_PEOPLE);
}
List<ProductResponse> productResponses = findProductResponse(validProductList, productInfoPerNightList);
AccommodationImageResponse accommodationImageResponse = AccommodationImageResponse
.from(accommodationEntity.getImages());
AccommodationOptionResponse accommodationOptionResponse = AccommodationOptionResponse
.from(accommodationEntity.getOptions());
return AccommodationDetailListResponse.from(accommodationEntity, checkInDate,
checkOutDate, accommodationImageResponse,
accommodationOptionResponse, productResponses);
}
@Transactional(readOnly = true)
public ProductDetailResponse getProductDetail(
Long accommodationId, Long productId,
LocalDate checkInDate, LocalDate checkOutDate,
int personNumber) {
validateInputs(checkInDate, checkOutDate, personNumber);
Accommodation accommodationEntity = findAccommodation(accommodationId);
Product productEntity = productRepository.
findByIdAndAccommodationId(productId, accommodationId)
.orElseThrow(() -> new ProductException(ErrorType.NOT_FOUND));
if (personNumber > productEntity.getMaximumNumber()) {
throw new ProductException(ErrorType.INVALID_NUMBER_OF_PEOPLE);
}
List<ProductInfoPerNight> availableProductPerNights
= findAvailableProductPerNight(productId, checkInDate, checkOutDate);
int totalPrice = calculateTotalPrice(availableProductPerNights);
long expectedNights = ChronoUnit.DAYS.between(checkInDate, checkOutDate);
if (availableProductPerNights.size() < expectedNights) {
throw new ProductException(ErrorType.NOT_FOUND);
}
ProductImageResponse productImageResponse = ProductImageResponse.from(
productEntity.getProductImage());
ProductOptionResponse productOptionResponse = ProductOptionResponse.from(
productEntity.getProductOption());
return ProductDetailResponse.from(productEntity, accommodationEntity.getName(),
availableProductPerNights.get(0).getPrice(), totalPrice, (int) expectedNights,
productImageResponse, productOptionResponse);
}
private void validateInputs(LocalDate checkInDate, LocalDate checkOutDate,
int personNumber) {
if (!isCheckInValid(checkInDate)) {
throw new AccommodationException(ErrorType.INVALID_CHECK_IN);
}
if (!isCheckOutValid(checkInDate, checkOutDate)) {
throw new AccommodationException(ErrorType.INVALID_CHECK_OUT);
}
if (personNumber < 1) {
throw new AccommodationException(ErrorType.INVALID_NUMBER_OF_PEOPLE);
}
}
private Accommodation findAccommodation(Long accommodationId) {
return accommodationRepository.findById(accommodationId)
.orElseThrow(() -> new AccommodationException(ErrorType.NOT_FOUND));
}
private List<Product> findProductList(List<Product> productList, List<ProductInfoPerNight> productInfoPerNightList,
LocalDate checkInDate, LocalDate checkOutDate,
int personNumber) {
Map<Long, List<ProductInfoPerNight>> perNightMap = productInfoPerNightList.stream()
.collect(Collectors.groupingBy(p -> p.getProduct().getId()));
return productList.stream()
.filter(product -> {
List<ProductInfoPerNight> infoPerNights = perNightMap.get(product.getId());
if (infoPerNights == null ||
infoPerNights.size() < ChronoUnit.DAYS.between(checkInDate, checkOutDate)) {
return false;
}
return personNumber <= product.getMaximumNumber();
})
.collect(Collectors.toList());
}
private List<ProductResponse> findProductResponse(List<Product> productList,
List<ProductInfoPerNight> productInfoPerNightList) {
Map<Long, List<ProductInfoPerNight>> perNightMap = productInfoPerNightList.stream()
.collect(Collectors.groupingBy(p -> p.getProduct().getId()));
return productList.stream()
.map(product -> {
ProductImageResponse productImageResponse = ProductImageResponse.from(product.getProductImage());
int minCount = perNightMap.get(product.getId()).stream()
.mapToInt(ProductInfoPerNight::getCount)
.min()
.orElse(0);
return ProductResponse.from(product, minCount, productImageResponse);
})
.collect(Collectors.toList());
}
private List<ProductInfoPerNight> findAvailableProductPerNight(Long productId, LocalDate checkInDate,
LocalDate checkOutDate) {
List<ProductInfoPerNight> infoPerNightList = productInfoPerNightRepository
.findByProductIdAndDateRange(productId, checkInDate, checkOutDate);
return infoPerNightList;
}
private int calculateTotalPrice(List<ProductInfoPerNight> productInfoPerNightList) {
return productInfoPerNightList.stream()
.mapToInt(ProductInfoPerNight::getPrice)
.sum();
}
}
728x90
'JAVA > 프로젝트' 카테고리의 다른 글
스프링부트 스케줄링 적용 @EnableScheduling (0) | 2024.07.16 |
---|---|
카카오맵 Rest API - 주소로 위도, 경도 반환하기 (0) | 2024.07.13 |
리팩토링: DB접근 줄여 실행 속도 향상 시키기 (0) | 2024.06.29 |
리팩토링: DB접근 줄이기 (0) | 2024.06.29 |
배달 플랫폼 백엔드 : rabbitmq 프로듀서 설정 (2) | 2024.06.14 |