diff --git a/backend/src/main/java/org/ftclub/cabinet/dto/UserBlackholeInfoDto.java b/backend/src/main/java/org/ftclub/cabinet/dto/UserBlackholeInfoDto.java
index 2ac7e21f3..7e0772a5a 100644
--- a/backend/src/main/java/org/ftclub/cabinet/dto/UserBlackholeInfoDto.java
+++ b/backend/src/main/java/org/ftclub/cabinet/dto/UserBlackholeInfoDto.java
@@ -4,6 +4,7 @@
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.ToString;
+import org.ftclub.cabinet.user.domain.User;
/**
* 유저의 식별자, 이름, 이메일, 블랙홀 날짜를 반환하는 DTO입니다.
@@ -22,4 +23,7 @@ public static UserBlackholeInfoDto of(Long userId, String name, String email,
LocalDateTime blackHoledAt) {
return new UserBlackholeInfoDto(userId, name, email, blackHoledAt);
}
+ public static UserBlackholeInfoDto of(User user) {
+ return new UserBlackholeInfoDto(user.getUserId(), user.getName(), user.getEmail(), user.getBlackholedAt());
+ }
}
diff --git a/backend/src/main/java/org/ftclub/cabinet/event/BlackholedUserLentEventListener.java b/backend/src/main/java/org/ftclub/cabinet/event/BlackholedUserLentEventListener.java
new file mode 100644
index 000000000..b2478601b
--- /dev/null
+++ b/backend/src/main/java/org/ftclub/cabinet/event/BlackholedUserLentEventListener.java
@@ -0,0 +1,24 @@
+package org.ftclub.cabinet.event;
+
+import lombok.RequiredArgsConstructor;
+import lombok.extern.log4j.Log4j2;
+import org.ftclub.cabinet.dto.UserBlackholeInfoDto;
+import org.ftclub.cabinet.utils.blackhole.manager.BlackholeManager;
+import org.springframework.context.event.EventListener;
+import org.springframework.stereotype.Component;
+
+@Log4j2
+@Component
+//@EnableAsync
+@RequiredArgsConstructor
+public class BlackholedUserLentEventListener {
+
+ private final BlackholeManager blackholeManager;
+
+ // @Async
+ @EventListener
+ public void handleBlackholedUserLentAttemptingEvent(UserBlackholeInfoDto userBlackholeInfoDto) {
+ log.info("Called handleBlackholedUserLentAttemptingEvent");
+ blackholeManager.handleBlackhole(userBlackholeInfoDto);
+ }
+}
diff --git a/backend/src/main/java/org/ftclub/cabinet/exception/CustomExceptionStatus.java b/backend/src/main/java/org/ftclub/cabinet/exception/CustomExceptionStatus.java
new file mode 100644
index 000000000..471523561
--- /dev/null
+++ b/backend/src/main/java/org/ftclub/cabinet/exception/CustomExceptionStatus.java
@@ -0,0 +1,30 @@
+package org.ftclub.cabinet.exception;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+import org.springframework.http.HttpStatus;
+
+/**
+ * {@link CustomServiceException}을 위한 exception 클래스. 생성할 exception에 대한 정보를 담고있다.
+ */
+@JsonFormat(shape = JsonFormat.Shape.OBJECT)
+@RequiredArgsConstructor
+@Getter
+public class CustomExceptionStatus {
+ private final int statusCode;
+ private final String message;
+ private final String error;
+
+ public CustomExceptionStatus(HttpStatus status, String message) {
+ this.statusCode = status.value();
+ this.message = message;
+ this.error = status.getReasonPhrase();
+ }
+
+ public CustomExceptionStatus(ExceptionStatus status, String message) {
+ this.statusCode = status.getStatusCode();
+ this.message = status.getMessage() + "\n" + message;
+ this.error = status.getError();
+ }
+}
diff --git a/backend/src/main/java/org/ftclub/cabinet/exception/CustomServiceException.java b/backend/src/main/java/org/ftclub/cabinet/exception/CustomServiceException.java
new file mode 100644
index 000000000..578eb53e0
--- /dev/null
+++ b/backend/src/main/java/org/ftclub/cabinet/exception/CustomServiceException.java
@@ -0,0 +1,21 @@
+package org.ftclub.cabinet.exception;
+
+/**
+ * Service에서 throw 하는 Exception 중 오류메세지를 커스텀 가능한 Exception
+ * @see CustomExceptionStatus
+ */
+public class CustomServiceException extends RuntimeException {
+
+ final CustomExceptionStatus status;
+
+ /**
+ * @param status exception에 대한 정보에 대한 enum
+ */
+ public CustomServiceException(CustomExceptionStatus status) {
+ this.status = status;
+ }
+
+ public CustomExceptionStatus getStatus() {
+ return status;
+ }
+}
diff --git a/backend/src/main/java/org/ftclub/cabinet/exception/ExceptionController.java b/backend/src/main/java/org/ftclub/cabinet/exception/ExceptionController.java
index 8c63fbc94..8b11cc9c5 100644
--- a/backend/src/main/java/org/ftclub/cabinet/exception/ExceptionController.java
+++ b/backend/src/main/java/org/ftclub/cabinet/exception/ExceptionController.java
@@ -25,6 +25,14 @@ public ResponseEntity> serviceExceptionHandler(ServiceException e) {
.body(e.status);
}
+ @ExceptionHandler(CustomServiceException.class)
+ public ResponseEntity> customServiceExceptionHandler(CustomServiceException e) {
+ log.info("[CustomServiceException] {} : {}", e.status.getError(), e.status.getMessage());
+ return ResponseEntity
+ .status(e.status.getStatusCode())
+ .body(e.status);
+ }
+
@ExceptionHandler(DomainException.class)
public ResponseEntity> domainExceptionHandler(DomainException e) {
log.warn("[DomainException] {} : {}", e.status.getError(), e.status.getMessage());
@@ -33,4 +41,12 @@ public ResponseEntity> domainExceptionHandler(DomainException e) {
.body(e.status);
}
+ @ExceptionHandler(UtilException.class)
+ public ResponseEntity> utilExceptionHandler(UtilException e) {
+ log.warn("[UtilException] {} : {}", e.status.getError(), e.status.getMessage());
+ return ResponseEntity
+ .status(e.status.getStatusCode())
+ .body(e.status);
+ }
+
}
diff --git a/backend/src/main/java/org/ftclub/cabinet/exception/ExceptionStatus.java b/backend/src/main/java/org/ftclub/cabinet/exception/ExceptionStatus.java
index 8c4f399a0..97b10e89b 100644
--- a/backend/src/main/java/org/ftclub/cabinet/exception/ExceptionStatus.java
+++ b/backend/src/main/java/org/ftclub/cabinet/exception/ExceptionStatus.java
@@ -34,6 +34,7 @@ public enum ExceptionStatus {
SHARE_BANNED_USER(HttpStatus.BAD_REQUEST, "SHARE 밴 상태의 유저입니다."),
NOT_FOUND_BAN_HISTORY(HttpStatus.NOT_FOUND, "현재 정지 상태인 유저가 아닙니다."),
BLACKHOLED_USER(HttpStatus.BAD_REQUEST, "블랙홀 상태의 유저입니다."),
+ BLACKHOLE_REFRESHING(HttpStatus.BAD_REQUEST, "블랙홀 갱신 중 입니다.\n잠시 후에 다시 시도해주세요."),
UNAUTHORIZED_ADMIN(HttpStatus.UNAUTHORIZED, "관리자 로그인 정보가 유효하지 않습니다\n다시 로그인해주세요"),
UNAUTHORIZED_USER(HttpStatus.UNAUTHORIZED, "사용자 로그인 정보가 유효하지 않습니다\n다시 로그인해주세요"),
EXTERNAL_API_EXCEPTION(HttpStatus.BAD_REQUEST, "외부 API와 통신 중 에러가 발생했습니다"),
@@ -41,7 +42,6 @@ public enum ExceptionStatus {
CLUB_HAS_LENT_CABINET(HttpStatus.NOT_ACCEPTABLE, "대여 중인 사물함을 반납 후 삭제할 수 있습니다."),
;
-
final private int statusCode;
final private String message;
final private String error;
diff --git a/backend/src/main/java/org/ftclub/cabinet/exception/UtilException.java b/backend/src/main/java/org/ftclub/cabinet/exception/UtilException.java
new file mode 100644
index 000000000..d626a0fe5
--- /dev/null
+++ b/backend/src/main/java/org/ftclub/cabinet/exception/UtilException.java
@@ -0,0 +1,23 @@
+package org.ftclub.cabinet.exception;
+
+/**
+ * Util에서 throw하는 exception들을 위한 exception 사용 예시:
+ *
+ * {@code throw new UtilException(ExceptionStatus.NOT_FOUND_USER);}
+ *
+ * 만약 새로운 exception을 만들 필요가 있다면 {@link ExceptionStatus}에서 새로운 enum값을 추가하면 된다.
+ * @see org.ftclub.cabinet.exception.ExceptionStatus
+ */
+
+public class UtilException extends RuntimeException {
+
+ final ExceptionStatus status;
+
+ /**
+ * @param status exception에 대한 정보에 대한 enum
+ */
+ public UtilException(ExceptionStatus status) {
+ this.status = status;
+ }
+
+}
diff --git a/backend/src/main/java/org/ftclub/cabinet/lent/domain/LentPolicyImpl.java b/backend/src/main/java/org/ftclub/cabinet/lent/domain/LentPolicyImpl.java
index 776c13c61..a39b8b081 100644
--- a/backend/src/main/java/org/ftclub/cabinet/lent/domain/LentPolicyImpl.java
+++ b/backend/src/main/java/org/ftclub/cabinet/lent/domain/LentPolicyImpl.java
@@ -1,30 +1,31 @@
package org.ftclub.cabinet.lent.domain;
-import java.time.LocalDate;
-import java.util.Date;
+import java.time.LocalDateTime;
+import java.util.List;
import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.ftclub.cabinet.cabinet.domain.Cabinet;
import org.ftclub.cabinet.cabinet.domain.CabinetStatus;
import org.ftclub.cabinet.cabinet.domain.LentType;
import org.ftclub.cabinet.config.CabinetProperties;
+import org.ftclub.cabinet.dto.UserBlackholeInfoDto;
import org.ftclub.cabinet.exception.DomainException;
import org.ftclub.cabinet.exception.ExceptionStatus;
import org.ftclub.cabinet.user.domain.BanHistory;
import org.ftclub.cabinet.user.domain.User;
import org.ftclub.cabinet.user.domain.UserRole;
import org.ftclub.cabinet.utils.DateUtil;
+import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Component;
-import java.time.LocalDateTime;
-import java.util.List;
-
@Component
@RequiredArgsConstructor
@Log4j2
public class LentPolicyImpl implements LentPolicy {
private final CabinetProperties cabinetProperties;
+ private final ApplicationEventPublisher publisher;
+
private LocalDateTime generateSharedCabinetExpirationDate(LocalDateTime now,
CabinetStatus cabinetStatus, LentHistory activeLentHistory) {
@@ -78,10 +79,11 @@ public LocalDateTime generateExpirationDate(LocalDateTime now, Cabinet cabinet,
@Override
public void applyExpirationDate(LentHistory curHistory, List beforeActiveHistories,
LocalDateTime expiredAt) {
- log.info("Called applyExpirationDate curHistory: {}, beforeActiveHistories: {}, expiredAt: {}",
+ log.info(
+ "Called applyExpirationDate curHistory: {}, beforeActiveHistories: {}, expiredAt: {}",
curHistory, beforeActiveHistories, expiredAt);
- if (expiredAt == null){
+ if (expiredAt == null) {
throw new DomainException(ExceptionStatus.INVALID_ARGUMENT);
}
@@ -105,17 +107,15 @@ public LentPolicyStatus verifyUserForLent(User user, Cabinet cabinet, int userAc
if (userActiveLentCount >= 1) {
return LentPolicyStatus.ALREADY_LENT_USER;
}
-// TODO: 현재 구조에서는 DB 정합성 문제를 일으키는 코드입니다.
-// 블랙홀에 빠진 유저 대여 로직을 막는다고 하면, BlackholeManager.handleBlackhole()을 통해
-// 실제 DB에 반영되기 전에 블랙홀에 빠진 유저를 걸러낼 수 있습니다.
-// 하지만, 현재는 BlackholeManager <-> LentService 간의 순환 참조가 발생하는데,
-// BlackholeManager는 스케줄러에 의해 빈에 등록되는 컴포넌트이므로
-// 현재 구조상으로는 @Lazy 어노테이션을 통해 순환 참조 문제를 해결할 수 없습니다.
-// 추후 다른 방식으로 구조적인 리팩토링이 필요한 부분입니다..!
-// if (user.getBlackholedAt() != null && user.getBlackholedAt()
-// .isBefore(LocalDateTime.now())) {
-// return LentPolicyStatus.BLACKHOLED_USER;
-// }
+ if (user.getBlackholedAt() != null && user.getBlackholedAt()
+ .isBefore(LocalDateTime.now())) {
+ publisher.publishEvent(UserBlackholeInfoDto.of(user));
+ if (user.getBlackholedAt() != null && user.getBlackholedAt()
+ .isBefore(LocalDateTime.now())) {
+ return LentPolicyStatus.BLACKHOLED_USER;
+ }
+ }
+
// 유저가 페널티 2 종류 이상 받을 수 있나? <- 실제로 그럴리 없지만 lentPolicy 객체는 그런 사실을 모르고, 유연하게 구현?
if (userActiveBanList == null || userActiveBanList.size() == 0) {
return LentPolicyStatus.FINE;
diff --git a/backend/src/main/java/org/ftclub/cabinet/lent/repository/LentOptionalFetcher.java b/backend/src/main/java/org/ftclub/cabinet/lent/repository/LentOptionalFetcher.java
index fc7c4a846..22a63e185 100644
--- a/backend/src/main/java/org/ftclub/cabinet/lent/repository/LentOptionalFetcher.java
+++ b/backend/src/main/java/org/ftclub/cabinet/lent/repository/LentOptionalFetcher.java
@@ -10,7 +10,6 @@
import org.ftclub.cabinet.exception.ExceptionStatus;
import org.ftclub.cabinet.exception.ServiceException;
import org.ftclub.cabinet.lent.domain.LentHistory;
-import org.ftclub.cabinet.lent.domain.LentPolicyStatus;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
@@ -91,41 +90,6 @@ public LentHistory getActiveLentHistoryWithUserId(Long userId) {
.orElseThrow(() -> new ServiceException(ExceptionStatus.NO_LENT_CABINET));
}
- /**
- * 정책에 대한 결과 상태({@link LentPolicyStatus})에 맞는 적절한 {@link ServiceException}을 throw합니다.
- *
- * @param status 정책에 대한 결과 상태
- * @throws ServiceException 정책에 따라 다양한 exception이 throw될 수 있습니다.
- */
- public void handlePolicyStatus(LentPolicyStatus status) {
- log.info("Called handlePolicyStatus status: {}", status);
- switch (status) {
- case FINE:
- break;
- case BROKEN_CABINET:
- throw new ServiceException(ExceptionStatus.LENT_BROKEN);
- case FULL_CABINET:
- throw new ServiceException(ExceptionStatus.LENT_FULL);
- case OVERDUE_CABINET:
- throw new ServiceException(ExceptionStatus.LENT_EXPIRED);
- case LENT_CLUB:
- throw new ServiceException(ExceptionStatus.LENT_CLUB);
- case IMMINENT_EXPIRATION:
- throw new ServiceException(ExceptionStatus.LENT_EXPIRE_IMMINENT);
- case ALREADY_LENT_USER:
- throw new ServiceException(ExceptionStatus.LENT_ALREADY_EXISTED);
- case ALL_BANNED_USER:
- throw new ServiceException(ExceptionStatus.ALL_BANNED_USER);
- case SHARE_BANNED_USER:
- throw new ServiceException(ExceptionStatus.SHARE_BANNED_USER);
- case BLACKHOLED_USER:
- throw new ServiceException(ExceptionStatus.BLACKHOLED_USER);
- case NOT_USER:
- case INTERNAL_ERROR:
- default:
- throw new ServiceException(ExceptionStatus.INTERNAL_SERVER_ERROR);
- }
- }
/**
* 사물함에 남은 자리가 있는 지 확인합니다. 남은 자리가 없으면 throw합니다.
diff --git a/backend/src/main/java/org/ftclub/cabinet/lent/service/LentServiceImpl.java b/backend/src/main/java/org/ftclub/cabinet/lent/service/LentServiceImpl.java
index 6aac3db9f..09fd839b4 100644
--- a/backend/src/main/java/org/ftclub/cabinet/lent/service/LentServiceImpl.java
+++ b/backend/src/main/java/org/ftclub/cabinet/lent/service/LentServiceImpl.java
@@ -1,12 +1,25 @@
package org.ftclub.cabinet.lent.service;
+import static org.ftclub.cabinet.exception.ExceptionStatus.ALL_BANNED_USER;
+
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.List;
+import java.util.Optional;
+import java.util.stream.Collectors;
+import javax.transaction.Transactional;
import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.ftclub.cabinet.cabinet.domain.Cabinet;
import org.ftclub.cabinet.cabinet.repository.CabinetOptionalFetcher;
import org.ftclub.cabinet.dto.ActiveLentHistoryDto;
+import org.ftclub.cabinet.exception.CustomExceptionStatus;
+import org.ftclub.cabinet.exception.CustomServiceException;
+import org.ftclub.cabinet.exception.ExceptionStatus;
+import org.ftclub.cabinet.exception.ServiceException;
import org.ftclub.cabinet.lent.domain.LentHistory;
import org.ftclub.cabinet.lent.domain.LentPolicy;
+import org.ftclub.cabinet.lent.domain.LentPolicyStatus;
import org.ftclub.cabinet.lent.repository.LentOptionalFetcher;
import org.ftclub.cabinet.lent.repository.LentRepository;
import org.ftclub.cabinet.mapper.LentMapper;
@@ -17,147 +30,199 @@
import org.ftclub.cabinet.user.service.UserService;
import org.springframework.stereotype.Service;
-import javax.transaction.Transactional;
-import java.time.LocalDateTime;
-import java.util.List;
-import java.util.stream.Collectors;
-
@Service
@RequiredArgsConstructor
@Transactional
@Log4j2
public class LentServiceImpl implements LentService {
- private final LentRepository lentRepository;
- private final LentPolicy lentPolicy;
- private final LentOptionalFetcher lentOptionalFetcher;
- private final CabinetOptionalFetcher cabinetOptionalFetcher;
- private final UserOptionalFetcher userExceptionHandler;
- private final UserService userService;
- private final BanHistoryRepository banHistoryRepository;
- private final LentMapper lentMapper;
-
- @Override
- public void startLentCabinet(Long userId, Long cabinetId) {
- log.info("Called startLentCabinet: {}, {}", userId, cabinetId);
- LocalDateTime now = LocalDateTime.now();
- Cabinet cabinet = cabinetOptionalFetcher.getCabinetForUpdate(cabinetId);
- User user = userExceptionHandler.getUser(userId);
- int userActiveLentCount = lentRepository.countUserActiveLent(userId);
- List userActiveBanList = banHistoryRepository.findUserActiveBanList(userId,
- now);
- // 대여 가능한 유저인지 확인
- lentOptionalFetcher.handlePolicyStatus(
- lentPolicy.verifyUserForLent(user, cabinet, userActiveLentCount,
- userActiveBanList));
- List cabinetActiveLentHistories = lentRepository.findAllActiveLentByCabinetId(
- cabinetId);
- // 대여 가능한 캐비넷인지 확인
- lentOptionalFetcher.handlePolicyStatus(
- lentPolicy.verifyCabinetForLent(cabinet, cabinetActiveLentHistories,
- now));
- // 캐비넷 상태 변경
- cabinet.specifyStatusByUserCount(cabinetActiveLentHistories.size() + 1);
- LocalDateTime expiredAt = lentPolicy.generateExpirationDate(now, cabinet,
- cabinetActiveLentHistories);
- LentHistory lentHistory = LentHistory.of(now, expiredAt, userId, cabinetId);
- // 연체 시간 적용
- lentPolicy.applyExpirationDate(lentHistory, cabinetActiveLentHistories, expiredAt);
- lentRepository.save(lentHistory);
- }
-
- @Override
- public void startLentClubCabinet(Long userId, Long cabinetId) {
- log.debug("Called startLentClubCabinet: {}, {}", userId, cabinetId);
- Cabinet cabinet = cabinetOptionalFetcher.getClubCabinet(cabinetId);
- lentOptionalFetcher.checkExistedSpace(cabinetId);
- LocalDateTime expirationDate = lentPolicy.generateExpirationDate(LocalDateTime.now(),
- cabinet, null);
- LentHistory result =
- LentHistory.of(LocalDateTime.now(), expirationDate, userId, cabinetId);
- lentRepository.save(result);
- cabinet.specifyStatusByUserCount(1); // todo : policy에서 관리
- }
-
- @Override
- public void endLentCabinet(Long userId) {
- log.debug("Called endLentCabinet: {}", userId);
- LentHistory lentHistory = returnCabinetByUserId(userId);
- Cabinet cabinet = cabinetOptionalFetcher.getCabinetForUpdate(lentHistory.getCabinetId());
- // cabinetType도 인자로 전달하면 좋을 거 같습니다 (공유사물함 3일이내 반납 페널티)
- userService.banUser(userId, cabinet.getLentType(), lentHistory.getStartedAt(),
- lentHistory.getEndedAt(), lentHistory.getExpiredAt());
- }
-
- @Override
- public void terminateLentCabinet(Long userId) {
- log.debug("Called terminateLentCabinet: {}", userId);
- returnCabinetByUserId(userId);
- }
-
- @Override
- public void terminateLentByCabinetId(Long cabinetId) {
- log.debug("Called terminateLentByCabinetId: {}", cabinetId);
- returnCabinetByCabinetId(cabinetId);
- }
-
- // cabinetId로 return하는 경우에서, 공유 사물함과 개인 사물함의 경우에 대한 분기가 되어 있지 않음.
- // 또한 어드민의 경우에서 사용하는 returnByCabinetId와 유저가 사용하는 returnByCabinetId가 다른 상황이므로
- // (어드민의 경우에는 뭐든지 전체 반납, 유저가 사용하는 경우에는 본인이 사용하는 사물함에 대한 반납)
- // 유저가 사용하는 경우에 대해서는 userId로만 쓰게하든, 한 방식으로만 사용하게끔 해야함 - 함수를 쪼갤 가능성도 있음.
- // 우선 현재 관리자만 쓰고 있고, 한 군데에서만 사용되므로 List로 전체 반납을 하도록 구현, 이에 대한 논의는 TO-DO
- private List returnCabinetByCabinetId(Long cabinetId) {
- log.debug("Called returnCabinetByCabinetId: {}", cabinetId);
- Cabinet cabinet = cabinetOptionalFetcher.getCabinetForUpdate(cabinetId);
- List lentHistories = lentOptionalFetcher.findAllActiveLentByCabinetId(
- cabinetId);
- lentHistories.forEach(lentHistory -> lentHistory.endLent(LocalDateTime.now()));
- cabinet.specifyStatusByUserCount(0); // policy로 빼는게..?
- cabinet.writeMemo("");
- cabinet.writeTitle("");
- return lentHistories;
- }
-
- private LentHistory returnCabinetByUserId(Long userId) {
- log.debug("Called returnCabinet: {}", userId);
- userExceptionHandler.getUser(userId);
- LentHistory lentHistory = lentOptionalFetcher.getActiveLentHistoryWithUserId(userId);
- Cabinet cabinet = cabinetOptionalFetcher.getCabinetForUpdate(lentHistory.getCabinetId());
- int activeLentCount = lentRepository.countCabinetActiveLent(lentHistory.getCabinetId());
- lentHistory.endLent(LocalDateTime.now());
- cabinet.specifyStatusByUserCount(activeLentCount - 1); // policy로 빠질만한 부분인듯?
- if (activeLentCount - 1 == 0) {
- cabinet.writeMemo("");
- cabinet.writeTitle("");
- }
- return lentHistory;
- }
-
- @Override
- public void assignLent(Long userId, Long cabinetId) {
- log.debug("Called assignLent: {}, {}", userId, cabinetId);
- userExceptionHandler.getUser(userId);
- Cabinet cabinet = cabinetOptionalFetcher.getCabinetForUpdate(cabinetId);
- lentOptionalFetcher.checkExistedSpace(cabinetId);
- LocalDateTime expirationDate = lentPolicy.generateExpirationDate(LocalDateTime.now(),
- cabinet, null);
- LentHistory result = LentHistory.of(LocalDateTime.now(), expirationDate, userId, cabinetId);
- cabinet.specifyStatusByUserCount(1);
- lentRepository.save(result);
- }
-
- @Override
- public List getAllActiveLentHistories() {
- log.debug("Called getAllActiveLentHistories");
- List lentHistories = lentOptionalFetcher.findAllActiveLentHistories();
- LocalDateTime now = LocalDateTime.now();
- return lentHistories.stream()
- .map(e -> lentMapper.toActiveLentHistoryDto(e,
- e.getUser(),
- e.getCabinet(),
- e.isExpired(now),
- e.getDaysUntilExpiration(now)
- ))
- .collect(Collectors.toList());
- }
+ private final LentRepository lentRepository;
+ private final LentPolicy lentPolicy;
+ private final LentOptionalFetcher lentOptionalFetcher;
+ private final CabinetOptionalFetcher cabinetOptionalFetcher;
+ private final UserOptionalFetcher userOptionalFetcher;
+ private final UserService userService;
+ private final BanHistoryRepository banHistoryRepository;
+ private final LentMapper lentMapper;
+
+ @Override
+ public void startLentCabinet(Long userId, Long cabinetId) {
+ log.info("Called startLentCabinet: {}, {}", userId, cabinetId);
+ LocalDateTime now = LocalDateTime.now();
+ Cabinet cabinet = cabinetOptionalFetcher.getCabinetForUpdate(cabinetId);
+ User user = userOptionalFetcher.getUser(userId);
+ int userActiveLentCount = lentRepository.countUserActiveLent(userId);
+ List userActiveBanList = banHistoryRepository.findUserActiveBanList(userId,
+ now);
+ // 대여 가능한 유저인지 확인
+ LentPolicyStatus userPolicyStatus = lentPolicy.verifyUserForLent(user, cabinet,
+ userActiveLentCount, userActiveBanList);
+ handlePolicyStatus(userPolicyStatus, userActiveBanList); // UserPolicyStatus 와 LentPolicyStatus 가 분리해야 하지않는가? 23/8/15
+ List cabinetActiveLentHistories = lentRepository.findAllActiveLentByCabinetId(
+ cabinetId);
+
+ // 대여 가능한 캐비넷인지 확인
+ LentPolicyStatus cabinetPolicyStatus = lentPolicy.verifyCabinetForLent(cabinet,
+ cabinetActiveLentHistories,
+ now);
+ handlePolicyStatus(cabinetPolicyStatus, userActiveBanList); // UserPolicyStatus 와 LentPolicyStatus 가 분리해야 하지않는가? 23/8/15
+
+ // 캐비넷 상태 변경
+ cabinet.specifyStatusByUserCount(cabinetActiveLentHistories.size() + 1);
+ LocalDateTime expiredAt = lentPolicy.generateExpirationDate(now, cabinet,
+ cabinetActiveLentHistories);
+ LentHistory lentHistory = LentHistory.of(now, expiredAt, userId, cabinetId);
+
+ // 연체 시간 적용
+ lentPolicy.applyExpirationDate(lentHistory, cabinetActiveLentHistories, expiredAt);
+ lentRepository.save(lentHistory);
+ }
+
+ @Override
+ public void startLentClubCabinet(Long userId, Long cabinetId) {
+ log.debug("Called startLentClubCabinet: {}, {}", userId, cabinetId);
+ Cabinet cabinet = cabinetOptionalFetcher.getClubCabinet(cabinetId);
+ lentOptionalFetcher.checkExistedSpace(cabinetId);
+ LocalDateTime expirationDate = lentPolicy.generateExpirationDate(LocalDateTime.now(),
+ cabinet, null);
+ LentHistory result =
+ LentHistory.of(LocalDateTime.now(), expirationDate, userId, cabinetId);
+ lentRepository.save(result);
+ cabinet.specifyStatusByUserCount(1); // todo : policy에서 관리
+ }
+
+ @Override
+ public void endLentCabinet(Long userId) {
+ log.debug("Called endLentCabinet: {}", userId);
+ LentHistory lentHistory = returnCabinetByUserId(userId);
+ Cabinet cabinet = cabinetOptionalFetcher.getCabinetForUpdate(lentHistory.getCabinetId());
+ // cabinetType도 인자로 전달하면 좋을 거 같습니다 (공유사물함 3일이내 반납 페널티)
+ userService.banUser(userId, cabinet.getLentType(), lentHistory.getStartedAt(),
+ lentHistory.getEndedAt(), lentHistory.getExpiredAt());
+ }
+
+ @Override
+ public void terminateLentCabinet(Long userId) {
+ log.debug("Called terminateLentCabinet: {}", userId);
+ returnCabinetByUserId(userId);
+ }
+
+ @Override
+ public void terminateLentByCabinetId(Long cabinetId) {
+ log.debug("Called terminateLentByCabinetId: {}", cabinetId);
+ returnCabinetByCabinetId(cabinetId);
+ }
+
+ // cabinetId로 return하는 경우에서, 공유 사물함과 개인 사물함의 경우에 대한 분기가 되어 있지 않음.
+ // 또한 어드민의 경우에서 사용하는 returnByCabinetId와 유저가 사용하는 returnByCabinetId가 다른 상황이므로
+ // (어드민의 경우에는 뭐든지 전체 반납, 유저가 사용하는 경우에는 본인이 사용하는 사물함에 대한 반납)
+ // 유저가 사용하는 경우에 대해서는 userId로만 쓰게하든, 한 방식으로만 사용하게끔 해야함 - 함수를 쪼갤 가능성도 있음.
+ // 우선 현재 관리자만 쓰고 있고, 한 군데에서만 사용되므로 List로 전체 반납을 하도록 구현, 이에 대한 논의는 TO-DO
+ private List returnCabinetByCabinetId(Long cabinetId) {
+ log.debug("Called returnCabinetByCabinetId: {}", cabinetId);
+ Cabinet cabinet = cabinetOptionalFetcher.getCabinetForUpdate(cabinetId);
+ List lentHistories = lentOptionalFetcher.findAllActiveLentByCabinetId(
+ cabinetId);
+ lentHistories.forEach(lentHistory -> lentHistory.endLent(LocalDateTime.now()));
+ cabinet.specifyStatusByUserCount(0); // policy로 빼는게..?
+ cabinet.writeMemo("");
+ cabinet.writeTitle("");
+ return lentHistories;
+ }
+
+ private LentHistory returnCabinetByUserId(Long userId) {
+ log.debug("Called returnCabinet: {}", userId);
+ userOptionalFetcher.getUser(userId);
+ LentHistory lentHistory = lentOptionalFetcher.getActiveLentHistoryWithUserId(userId);
+ Cabinet cabinet = cabinetOptionalFetcher.getCabinetForUpdate(lentHistory.getCabinetId());
+ int activeLentCount = lentRepository.countCabinetActiveLent(lentHistory.getCabinetId());
+ lentHistory.endLent(LocalDateTime.now());
+ cabinet.specifyStatusByUserCount(activeLentCount - 1); // policy로 빠질만한 부분인듯?
+ if (activeLentCount - 1 == 0) {
+ cabinet.writeMemo("");
+ cabinet.writeTitle("");
+ }
+ return lentHistory;
+ }
+
+ @Override
+ public void assignLent(Long userId, Long cabinetId) {
+ log.debug("Called assignLent: {}, {}", userId, cabinetId);
+ userOptionalFetcher.getUser(userId);
+ Cabinet cabinet = cabinetOptionalFetcher.getCabinetForUpdate(cabinetId);
+ lentOptionalFetcher.checkExistedSpace(cabinetId);
+ LocalDateTime expirationDate = lentPolicy.generateExpirationDate(LocalDateTime.now(),
+ cabinet, null);
+ LentHistory result = LentHistory.of(LocalDateTime.now(), expirationDate, userId, cabinetId);
+ cabinet.specifyStatusByUserCount(1);
+ lentRepository.save(result);
+ }
+
+ @Override
+ public List getAllActiveLentHistories() {
+ log.debug("Called getAllActiveLentHistories");
+ List lentHistories = lentOptionalFetcher.findAllActiveLentHistories();
+ LocalDateTime now = LocalDateTime.now();
+ return lentHistories.stream()
+ .map(e -> lentMapper.toActiveLentHistoryDto(e,
+ e.getUser(),
+ e.getCabinet(),
+ e.isExpired(now),
+ e.getDaysUntilExpiration(now)
+ ))
+ .collect(Collectors.toList());
+ }
+
+ /**
+ * 정책에 대한 결과 상태({@link LentPolicyStatus})에 맞는 적절한 {@link ServiceException}을 throw합니다.
+ *
+ * @param status 정책에 대한 결과 상태
+ * @throws ServiceException 정책에 따라 다양한 exception이 throw될 수 있습니다.
+ */
+ private void handlePolicyStatus(LentPolicyStatus status, List banHistory) {
+ log.info("Called handlePolicyStatus status: {}", status);
+ switch (status) {
+ case FINE:
+ break;
+ case BROKEN_CABINET:
+ throw new ServiceException(ExceptionStatus.LENT_BROKEN);
+ case FULL_CABINET:
+ throw new ServiceException(ExceptionStatus.LENT_FULL);
+ case OVERDUE_CABINET:
+ throw new ServiceException(ExceptionStatus.LENT_EXPIRED);
+ case LENT_CLUB:
+ throw new ServiceException(ExceptionStatus.LENT_CLUB);
+ case IMMINENT_EXPIRATION:
+ throw new ServiceException(ExceptionStatus.LENT_EXPIRE_IMMINENT);
+ case ALREADY_LENT_USER:
+ throw new ServiceException(ExceptionStatus.LENT_ALREADY_EXISTED);
+ case ALL_BANNED_USER:
+ case SHARE_BANNED_USER:
+ handleBannedUserResponse(status, banHistory.get(0));
+ case BLACKHOLED_USER:
+ throw new ServiceException(ExceptionStatus.BLACKHOLED_USER);
+ case NOT_USER:
+ case INTERNAL_ERROR:
+ default:
+ throw new ServiceException(ExceptionStatus.INTERNAL_SERVER_ERROR);
+ }
+ }
+
+ private void handleBannedUserResponse(LentPolicyStatus status, BanHistory banHistory) {
+ log.info("Called handleBannedUserResponse: {}", status);
+
+
+ LocalDateTime unbannedAt = banHistory.getUnbannedAt();
+ String unbannedTimeString = unbannedAt.format(
+ DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"));
+
+ if (status.equals(LentPolicyStatus.ALL_BANNED_USER)) {
+ throw new CustomServiceException(
+ new CustomExceptionStatus(ExceptionStatus.ALL_BANNED_USER, unbannedTimeString));
+ } else if (status.equals(LentPolicyStatus.SHARE_BANNED_USER)) {
+ throw new CustomServiceException(
+ new CustomExceptionStatus(ExceptionStatus.SHARE_BANNED_USER,
+ unbannedTimeString));
+ }
+ }
}
diff --git a/backend/src/main/java/org/ftclub/cabinet/user/repository/UserOptionalFetcher.java b/backend/src/main/java/org/ftclub/cabinet/user/repository/UserOptionalFetcher.java
index 0386d7e44..69e7b0527 100644
--- a/backend/src/main/java/org/ftclub/cabinet/user/repository/UserOptionalFetcher.java
+++ b/backend/src/main/java/org/ftclub/cabinet/user/repository/UserOptionalFetcher.java
@@ -2,6 +2,7 @@
import java.time.LocalDateTime;
import java.util.List;
+import java.util.Optional;
import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.ftclub.cabinet.exception.DomainException;
@@ -238,4 +239,12 @@ public BanHistory getRecentBanHistory(Long userId) {
}
return banHistory.get(0);
}
+
+ public BanHistory getActiveBanHistory(Long userId) {
+ log.debug("Called getActiveBanHistory: {}", userId);
+ Optional banHistory = banHistoryRepository.findRecentActiveBanHistoryByUserId(
+ userId,
+ LocalDateTime.now());
+ return banHistory.get();
+ }
}
diff --git a/backend/src/main/java/org/ftclub/cabinet/utils/blackhole/manager/BlackholeManager.java b/backend/src/main/java/org/ftclub/cabinet/utils/blackhole/manager/BlackholeManager.java
index 2c3b7ee93..92fcb5379 100644
--- a/backend/src/main/java/org/ftclub/cabinet/utils/blackhole/manager/BlackholeManager.java
+++ b/backend/src/main/java/org/ftclub/cabinet/utils/blackhole/manager/BlackholeManager.java
@@ -8,6 +8,7 @@
import org.ftclub.cabinet.dto.UserBlackholeInfoDto;
import org.ftclub.cabinet.exception.ExceptionStatus;
import org.ftclub.cabinet.exception.ServiceException;
+import org.ftclub.cabinet.exception.UtilException;
import org.ftclub.cabinet.lent.service.LentService;
import org.ftclub.cabinet.user.service.UserService;
import org.springframework.http.HttpStatus;
@@ -19,7 +20,7 @@
@Log4j2
public class BlackholeManager {
- private final FtApiManager ftAPIManager;
+ private final FtApiManager ftApiManager;
private final LentService lentService;
private final UserService userService;
@@ -30,8 +31,9 @@ public class BlackholeManager {
* @param jsonUserInfo JsonNode에 담긴 유저 정보
* @return 카뎃 여부
*/
- private Boolean isValidCadet(JsonNode jsonUserInfo) {
- log.info("isValidCadet {}", jsonUserInfo);
+ private boolean isValidCadet(JsonNode jsonUserInfo) {
+ log.debug("isValidCadet {}", jsonUserInfo);
+ log.info("isValidCadet");
return jsonUserInfo.get("cursus_users").size() >= 2;
}
@@ -54,11 +56,11 @@ private LocalDateTime parseBlackholedAt(JsonNode jsonUserInfo) {
* 갱신된 블랙홀 날짜를 바탕으로 블랙홀에 빠졌는지 확인한다.
*
* @param blackholedAtDate 블랙홀 날짜
- * @param now 현재 시간
* @return 블랙홀에 빠졌는지 여부
*/
- private Boolean isBlackholed(LocalDateTime blackholedAtDate, LocalDateTime now) {
- log.info("isBlackholed {} {}", blackholedAtDate, now);
+ private boolean isBlackholed(LocalDateTime blackholedAtDate) {
+ log.info("isBlackholed {} {}", blackholedAtDate);
+ LocalDateTime now = LocalDateTime.now();
if (blackholedAtDate == null || blackholedAtDate.isAfter(now)) {
return false;
} else {
@@ -82,10 +84,10 @@ private void handleNotCadet(UserBlackholeInfoDto userBlackholeInfoDto, LocalDate
* 블랙홀에 빠진 유저를 강제 반납 및 삭제 처리한다.
*
* @param userBlackholeInfoDto 유저 정보 {@link UserBlackholeInfoDto}
- * @param now 현재 시간
*/
- private void handleBlackholed(UserBlackholeInfoDto userBlackholeInfoDto, LocalDateTime now) {
+ private void handleBlackholed(UserBlackholeInfoDto userBlackholeInfoDto) {
log.info("{}는 블랙홀에 빠졌습니다.", userBlackholeInfoDto);
+ LocalDateTime now = LocalDateTime.now();
lentService.terminateLentCabinet(userBlackholeInfoDto.getUserId());
userService.deleteUser(userBlackholeInfoDto.getUserId(), now);
}
@@ -119,33 +121,102 @@ private void handleHttpClientError(UserBlackholeInfoDto userBlackholeInfoDto, Lo
}
}
- public void handleBlackhole(UserBlackholeInfoDto userBlackholeInfoDto) {
- log.info("called handleBlackhole {}", userBlackholeInfoDto);
+ /**
+ * 유저의 블랙홀 정보를 API 를 통해 요청하여 찾아온다.
+ *
+ * @param userName 유저 이름
+ * @return JsonNode 유저의 블랙홀 정보
+ * @throws ServiceException
+ */
+ private JsonNode getBlackholeInfo(String userName)
+ throws ServiceException, HttpClientErrorException {
+ log.info("called refreshBlackhole{}", userName);
+ JsonNode userInfoFromIntra = ftApiManager.getFtUsersInfoByName(
+ userName);
+
+ return userInfoFromIntra;
+ }
+
+
+ /**
+ * 유저의 블랙홀 날짜를 갱신하여 LocalDateTime으로 반환한다.
+ *
+ * @param userName 유저 이름
+ * @return 갱신된 블랙홀 날짜 LocalDateTime
+ */
+ private LocalDateTime refreshBlackholedAt(String userName) {
+ log.info("refreshBlackholedAt {}", userName);
+ JsonNode blackholeInfo = getBlackholeInfo(userName);
+ return parseBlackholedAt(blackholeInfo);
+ }
+
+ /**
+ * 유저속성의 블랙홀 날짜를 갱신한다.
+ *
+ * @param userId 유저 아이디
+ * @param blackholedAt 갱신할 블랙홀 날짜
+ */
+ private void updateUserBlackholedAt(Long userId, LocalDateTime blackholedAt) {
+ userService.updateUserBlackholedAt(userId, blackholedAt);
+ }
+
+
+ /**
+ * 스케쥴러가 샐행하는 블랙홀 처리 메서드 유저의 블랙홀 정보를 갱신하여 블랙홀에 빠졌는지 확인 후 처리한다.
+ *
+ * 블랙홀에 빠진경우 반납 / 계정 삭제처리 블랙홀에 빠지지 않은경우 블랙홀 날짜 갱신
+ *
+ * @param userInfoDto
+ */
+
+ public void handleBlackhole(UserBlackholeInfoDto userInfoDto) {
+ log.info("called handleBlackhole {}", userInfoDto);
LocalDateTime now = LocalDateTime.now();
try {
- JsonNode jsonUserInfo = ftAPIManager.getFtUsersInfoByName(
- userBlackholeInfoDto.getName());
- if (!isValidCadet(jsonUserInfo)) {
- handleNotCadet(userBlackholeInfoDto, now);
+ JsonNode jsonRefreshedUserInfo = getBlackholeInfo(userInfoDto.getName());
+ if (!isValidCadet(jsonRefreshedUserInfo)) {
+ handleNotCadet(userInfoDto, now);
return;
}
- LocalDateTime newBlackholedAt = parseBlackholedAt(jsonUserInfo);
+ LocalDateTime newBlackholedAt = parseBlackholedAt(jsonRefreshedUserInfo);
log.info("갱신된 블랙홀 날짜 {}", newBlackholedAt);
log.info("오늘 날짜 {}", now);
- if (isBlackholed(newBlackholedAt, now)) {
- handleBlackholed(userBlackholeInfoDto, now);
+ if (isBlackholed(newBlackholedAt)) {
+ handleBlackholed(userInfoDto);
} else {
- handleNotBlackholed(userBlackholeInfoDto, newBlackholedAt);
+ handleNotBlackholed(userInfoDto, newBlackholedAt);
}
} catch (HttpClientErrorException e) {
- handleHttpClientError(userBlackholeInfoDto, now, e);
+ handleHttpClientError(userInfoDto, now, e);
} catch (ServiceException e) {
if (e.getStatus().equals(ExceptionStatus.NO_LENT_CABINET)) {
- userService.deleteUser(userBlackholeInfoDto.getUserId(), now);
+ userService.deleteUser(userInfoDto.getUserId(), now);
}
+ else if (e.getStatus().equals(ExceptionStatus.OAUTH_BAD_GATEWAY))
+ log.info("handleBlackhole ServiceException {}", e.getStatus());
+ throw new UtilException(e.getStatus());
} catch (Exception e) {
- log.error("handleBlackhole Exception: {}", userBlackholeInfoDto, e);
+ log.error("handleBlackhole Exception: {}", userInfoDto, e);
+ }
+ }
+
+ // 따로 분리할 필요 없을듯..
+
+ /**
+ * 블랙홀 갱신 후 처리
+ *
+ * 블랙홀일 경우 반납 및 삭제 처리 블랙홀이 아닐경우 유저 정보(블랙홀일자) 업데이트
+ *
+ * @param userBlackholeInfoDto
+ */
+ public void blackholeRefresher(UserBlackholeInfoDto userBlackholeInfoDto) {
+ LocalDateTime refreshedBlackholedAt = refreshBlackholedAt(userBlackholeInfoDto.getName());
+ if (isBlackholed(refreshedBlackholedAt)) {
+ handleBlackholed(userBlackholeInfoDto);
+ throw new ServiceException(ExceptionStatus.BLACKHOLED_USER);
+ } else {
+ updateUserBlackholedAt(userBlackholeInfoDto.getUserId(), refreshedBlackholedAt);
}
}
}
diff --git a/backend/src/main/java/org/ftclub/cabinet/utils/scheduler/SystemScheduler.java b/backend/src/main/java/org/ftclub/cabinet/utils/scheduler/SystemScheduler.java
index 00c1ec84d..7a49c5d3e 100644
--- a/backend/src/main/java/org/ftclub/cabinet/utils/scheduler/SystemScheduler.java
+++ b/backend/src/main/java/org/ftclub/cabinet/utils/scheduler/SystemScheduler.java
@@ -29,8 +29,10 @@ public class SystemScheduler {
private final UserService userService;
private final BlackholeManager blackholeManager;
+ private static final long DELAY_TIME = 2000;
+
/**
- * 매일 자정마다 대여 기록을 확인하여, 연체 메일 발송 및 휴학생 처리를 트리거하는 메소드
+ * 매일 자정마다 대여 기록을 확인하여, 연체 메일 발송 및 휴학생 처리를 트리거하는 메소드 2초 간격으로 블랙홀 검증
*/
@Scheduled(cron = "${spring.schedule.cron.leave-absence}")
public void checkAllLents() {
@@ -39,9 +41,8 @@ public void checkAllLents() {
for (ActiveLentHistoryDto activeLent : activeLents) {
overdueManager.handleOverdue(activeLent);
leaveAbsenceManager.handleLeaveAbsence(activeLent.getUserId(), activeLent.getName());
- // 2초 간격으로 대여 검증
try {
- Thread.sleep(2000);
+ Thread.sleep(DELAY_TIME);
} catch (InterruptedException e) {
log.error(e.getMessage());
}
@@ -49,7 +50,7 @@ public void checkAllLents() {
}
/**
- * 매주 월요일 자정 42분에 블랙홀에 빠진 유저 처리를 트리거하는 메소드
+ * 매주 월요일 자정 42분에 블랙홀에 빠진 유저 처리를 트리거하는 메소드 2초 간격으로 블랙홀 검증
*/
@Scheduled(cron = "${spring.schedule.cron.risk-of-blackhole}")
public void checkRiskOfBlackhole() {
@@ -57,9 +58,8 @@ public void checkRiskOfBlackhole() {
List blackholeInfos = userService.getAllRiskOfBlackholeInfo();
for (UserBlackholeInfoDto blackholeInfo : blackholeInfos) {
blackholeManager.handleBlackhole(blackholeInfo);
- // 2초 간격으로 블랙홀 검증
try {
- Thread.sleep(2000);
+ Thread.sleep(DELAY_TIME);
} catch (InterruptedException e) {
log.error(e.getMessage());
}
@@ -67,7 +67,7 @@ public void checkRiskOfBlackhole() {
}
/**
- * 매월 1일 01시 42분에 블랙홀에 빠질 위험이 없는 유저들의 블랙홀 처리를 트리거하는 메소드
+ * 매월 1일 01시 42분에 블랙홀에 빠질 위험이 없는 유저들의 블랙홀 처리를 트리거하는 메소드 2초 간격으로 블랙홀 검증
*/
@Scheduled(cron = "${spring.schedule.cron.no-risk-of-blackhole}")
public void checkNoRiskOfBlackhole() {
@@ -75,9 +75,8 @@ public void checkNoRiskOfBlackhole() {
List blackholeInfos = userService.getAllNoRiskOfBlackholeInfo();
for (UserBlackholeInfoDto blackholeInfo : blackholeInfos) {
blackholeManager.handleBlackhole(blackholeInfo);
- // 2초 간격으로 블랙홀 검증
try {
- Thread.sleep(2000);
+ Thread.sleep(DELAY_TIME);
} catch (InterruptedException e) {
log.error(e.getMessage());
}
diff --git a/backend/src/main/resources/log4j2-local.yml b/backend/src/main/resources/log4j2-local.yml
index 83f5a42a6..7f1087801 100644
--- a/backend/src/main/resources/log4j2-local.yml
+++ b/backend/src/main/resources/log4j2-local.yml
@@ -18,13 +18,13 @@ Configuration:
-
name: org.springframework
# local 환경에서는 debug, production 환경에서는 info
- level: debug
+ level: info
additivity: false
AppenderRef:
- ref: console
-
name: org.ftclub.cabinet
- level: debug
+ level: info
additivity: false
AppenderRef:
- ref: console
diff --git a/backend/src/test/java/org/ftclub/cabinet/utils/blackhole/manager/BlackholeManagerUnitTest.java b/backend/src/test/java/org/ftclub/cabinet/utils/blackhole/manager/BlackholeManagerUnitTest.java
index 1fbebd57c..f1b6746fc 100644
--- a/backend/src/test/java/org/ftclub/cabinet/utils/blackhole/manager/BlackholeManagerUnitTest.java
+++ b/backend/src/test/java/org/ftclub/cabinet/utils/blackhole/manager/BlackholeManagerUnitTest.java
@@ -17,12 +17,8 @@
import org.ftclub.cabinet.auth.service.FtApiManager;
import org.ftclub.cabinet.config.FtApiProperties;
import org.ftclub.cabinet.dto.UserBlackholeInfoDto;
-import org.ftclub.cabinet.exception.ExceptionStatus;
-import org.ftclub.cabinet.exception.ServiceException;
import org.ftclub.cabinet.lent.service.LentService;
import org.ftclub.cabinet.user.service.UserService;
-import org.ftclub.cabinet.utils.ExceptionUtil;
-import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;