claims = tokenProvider
+// String accessToken = tokenProvider.createTokenForTestUser(testUser, LocalDateTime.now());
+// Cookie cookie = cookieManager.cookieOf("access_token",
+// accessToken);
+// cookieManager.setCookieToClient(res, cookie, "/", req.getServerName());
+// System.out.println("?????????????????????? cookie domain = ");
+// res.sendRedirect(DomainProperties.getLocal() + "/main");
+// res.sendRedirect(DomainProperties.getFeHost() + "/home");
+ }
}
diff --git a/backend/src/main/java/org/ftclub/cabinet/auth/domain/CookieManager.java b/backend/src/main/java/org/ftclub/cabinet/auth/domain/CookieManager.java
index 06e80e9c0..07766a7db 100644
--- a/backend/src/main/java/org/ftclub/cabinet/auth/domain/CookieManager.java
+++ b/backend/src/main/java/org/ftclub/cabinet/auth/domain/CookieManager.java
@@ -1,14 +1,13 @@
package org.ftclub.cabinet.auth.domain;
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import org.ftclub.cabinet.config.DomainProperties;
import org.ftclub.cabinet.config.JwtProperties;
import org.springframework.stereotype.Component;
-import javax.servlet.http.Cookie;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
/**
* 클라이언트의 쿠키를 관리하는 클래스입니다.
*/
@@ -48,7 +47,7 @@ public String getCookieValue(HttpServletRequest req, String name) {
* @param serverName 쿠키 도메인
*/
public void setCookieToClient(HttpServletResponse res, Cookie cookie, String path,
- String serverName) {
+ String serverName) {
cookie.setMaxAge(60 * 60 * 24 * jwtProperties.getExpiryDays());
cookie.setPath(path);
if (serverName.equals(domainProperties.getLocal())) {
@@ -56,6 +55,7 @@ public void setCookieToClient(HttpServletResponse res, Cookie cookie, String pat
} else {
cookie.setDomain(domainProperties.getCookieDomain());
}
+ System.out.println("?????????????????????? cookie domain = " + cookie.getDomain());
res.addCookie(cookie);
}
diff --git a/backend/src/main/java/org/ftclub/cabinet/auth/domain/TokenProvider.java b/backend/src/main/java/org/ftclub/cabinet/auth/domain/TokenProvider.java
index 8208db8a4..6dba0652c 100644
--- a/backend/src/main/java/org/ftclub/cabinet/auth/domain/TokenProvider.java
+++ b/backend/src/main/java/org/ftclub/cabinet/auth/domain/TokenProvider.java
@@ -1,8 +1,15 @@
package org.ftclub.cabinet.auth.domain;
+import static org.ftclub.cabinet.exception.ExceptionStatus.INVALID_ARGUMENT;
+import static org.ftclub.cabinet.exception.ExceptionStatus.UNAUTHORIZED_USER;
+
import com.fasterxml.jackson.databind.JsonNode;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
+import java.sql.Timestamp;
+import java.time.LocalDateTime;
+import java.util.HashMap;
+import java.util.Map;
import lombok.RequiredArgsConstructor;
import org.ftclub.cabinet.config.FtApiProperties;
import org.ftclub.cabinet.config.GoogleApiProperties;
@@ -13,14 +20,6 @@
import org.ftclub.cabinet.user.domain.UserRole;
import org.springframework.stereotype.Component;
-import java.sql.Timestamp;
-import java.time.LocalDateTime;
-import java.util.HashMap;
-import java.util.Map;
-
-import static org.ftclub.cabinet.exception.ExceptionStatus.INVALID_ARGUMENT;
-import static org.ftclub.cabinet.exception.ExceptionStatus.UNAUTHORIZED_USER;
-
/**
* API 제공자에 따라 JWT 토큰을 생성하는 클래스입니다.
*/
diff --git a/backend/src/main/java/org/ftclub/cabinet/auth/domain/TokenValidator.java b/backend/src/main/java/org/ftclub/cabinet/auth/domain/TokenValidator.java
index c3050fe0b..c081d6c35 100644
--- a/backend/src/main/java/org/ftclub/cabinet/auth/domain/TokenValidator.java
+++ b/backend/src/main/java/org/ftclub/cabinet/auth/domain/TokenValidator.java
@@ -1,5 +1,7 @@
package org.ftclub.cabinet.auth.domain;
+import static org.ftclub.cabinet.user.domain.AdminRole.MASTER;
+
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
@@ -7,6 +9,9 @@
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.MalformedJwtException;
import io.jsonwebtoken.UnsupportedJwtException;
+import java.security.Key;
+import java.util.Base64;
+import javax.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.ftclub.cabinet.config.DomainProperties;
@@ -18,12 +23,6 @@
import org.ftclub.cabinet.user.service.UserService;
import org.springframework.stereotype.Component;
-import javax.servlet.http.HttpServletRequest;
-import java.security.Key;
-import java.util.Base64;
-
-import static org.ftclub.cabinet.user.domain.AdminRole.MASTER;
-
/**
* 토큰의 유효성을 검사하는 클래스입니다.
*
@@ -34,119 +33,121 @@
@Slf4j
public class TokenValidator {
- private final MasterProperties masterProperties;
- private final DomainProperties domainProperties;
- private final JwtProperties jwtProperties;
- private final UserService userService;
+ private final MasterProperties masterProperties;
+ private final DomainProperties domainProperties;
+ private final JwtProperties jwtProperties;
+ private final UserService userService;
- /**
- * 토큰의 유효성을 검사합니다.
- *
- * 매 요청시 헤더에 Bearer 토큰으로 인증을 시도하기 때문에,
- *
- * 헤더에 bearer 방식으로 유효하게 토큰이 전달되었는지 검사합니다.
- *
- * USER_ONLY의 경우 검증하지 않습니다.
- *
- * @param req {@link HttpServletRequest}
- * @return 정상적인 방식의 토큰 요청인지, 유효한 토큰인지 여부
- */
- public Boolean isValidRequestWithLevel(HttpServletRequest req, AuthLevel authLevel)
- throws JsonProcessingException {
- String authHeader = req.getHeader("Authorization");
- if (authHeader == null || !authHeader.startsWith("Bearer ")) {
- return false;
- }
- String token = authHeader.substring(7);
- if (!isTokenValid(token, jwtProperties.getSigningKey())) {
- return false;
- }
- return isTokenAuthenticatable(token, authLevel);
- }
+ /**
+ * 토큰의 유효성을 검사합니다.
+ *
+ * 매 요청시 헤더에 Bearer 토큰으로 인증을 시도하기 때문에,
+ *
+ * 헤더에 bearer 방식으로 유효하게 토큰이 전달되었는지 검사합니다.
+ *
+ * USER_ONLY의 경우 검증하지 않습니다.
+ *
+ * @param req {@link HttpServletRequest}
+ * @return 정상적인 방식의 토큰 요청인지, 유효한 토큰인지 여부
+ */
+ public Boolean isValidRequestWithLevel(HttpServletRequest req, AuthLevel authLevel)
+ throws JsonProcessingException {
+ String authHeader = req.getHeader("Authorization");
+ if (authHeader == null || !authHeader.startsWith("Bearer ")) {
+ return false;
+ }
+ String token = authHeader.substring(7);
+ if (!isTokenValid(token, jwtProperties.getSigningKey())) {
+ return false;
+ }
+ return isTokenAuthenticatable(token, authLevel);
+ }
- /**
- * 토큰의 유효성을 검사합니다.
- *
- * JWT ParseBuilder의 parseClaimJws를 통해 토큰을 검사합니다.
- *
- * 만료되었거나, 잘못된(위, 변조된) 토큰이거스나, 지원되지 않는 토큰이면 false를 반환합니다.
- *
- * @param token 검사할 토큰
- * @return 토큰이 만료되거나 유효한지 아닌지 여부
- */
- public Boolean isTokenValid(String token, Key key) {
- try {
- Jwts.parserBuilder().setSigningKey(key).build()
- .parseClaimsJws(token);
- return true;
- } catch (MalformedJwtException e) {
- log.info("잘못된 JWT 서명입니다.");
- } catch (ExpiredJwtException e) {
- log.info("만료된 JWT 토큰입니다.");
- } catch (UnsupportedJwtException e) {
- log.info("지원되지 않는 JWT 토큰입니다.");
- } catch (IllegalArgumentException e) {
- log.info("JWT 토큰이 잘못되었습니다.");
- } catch (Exception e) {
- log.info("JWT 토큰 검사 중 알 수 없는 오류가 발생했습니다.");
- }
- return false;
- }
+ /**
+ * 토큰의 유효성을 검사합니다.
+ *
+ * JWT ParseBuilder의 parseClaimJws를 통해 토큰을 검사합니다.
+ *
+ * 만료되었거나, 잘못된(위, 변조된) 토큰이거스나, 지원되지 않는 토큰이면 false를 반환합니다.
+ *
+ * @param token 검사할 토큰
+ * @return 토큰이 만료되거나 유효한지 아닌지 여부
+ */
+ public Boolean isTokenValid(String token, Key key) {
+ try {
+ Jwts.parserBuilder().setSigningKey(key).build()
+ .parseClaimsJws(token);
+ return true;
+ } catch (MalformedJwtException e) {
+ log.info("잘못된 JWT 서명입니다.");
+ } catch (ExpiredJwtException e) {
+ log.info("만료된 JWT 토큰입니다.");
+ } catch (UnsupportedJwtException e) {
+ log.info("지원되지 않는 JWT 토큰입니다.");
+ } catch (IllegalArgumentException e) {
+ log.info("JWT 토큰이 잘못되었습니다.");
+ } catch (Exception e) {
+ log.info("JWT 토큰 검사 중 알 수 없는 오류가 발생했습니다.");
+ }
+ return false;
+ }
- /**
- * 토큰의 Payload를 JsonNode(JSON) 형식으로 가져옵니다.
- *
- * @param token 토큰
- * @return JSON 형식의 Payload
- * @throws JsonProcessingException
- */
- public JsonNode getPayloadJson(final String token) throws JsonProcessingException {
- ObjectMapper objectMapper = new ObjectMapper();
- final String payloadJWT = token.split("\\.")[1];
- Base64.Decoder decoder = Base64.getUrlDecoder();
+ /**
+ * 토큰의 Payload를 JsonNode(JSON) 형식으로 가져옵니다.
+ *
+ * @param token 토큰
+ * @return JSON 형식의 Payload
+ * @throws JsonProcessingException
+ */
+ public JsonNode getPayloadJson(final String token) throws JsonProcessingException {
+ ObjectMapper objectMapper = new ObjectMapper();
+ final String payloadJWT = token.split("\\.")[1];
+ Base64.Decoder decoder = Base64.getUrlDecoder();
- return objectMapper.readTree(new String(decoder.decode(payloadJWT)));
- }
+ return objectMapper.readTree(new String(decoder.decode(payloadJWT)));
+ }
- /**
- * 해당 토큰의 페이로드 정보가 인증 단계에 알맞는지 확인합니다.
- *
- * MASTER의 경우 현재 정적으로 관리하므로 이메일만 검증합니다.
- *
- *
- * @param token 토큰
- * @param authLevel 인증 단계
- * @return 페이로드 정보가 실제 DB와 일치하면 true를 반환합니다.
- */
- public boolean isTokenAuthenticatable(String token, AuthLevel authLevel)
- throws JsonProcessingException {
- String email = getPayloadJson(token).get("email").asText();
- if (email == null) {
- throw new DomainException(ExceptionStatus.INVALID_ARGUMENT);
- }
- switch (authLevel) {
- case USER_OR_ADMIN:
- return true;
- case USER_ONLY:
- return !isAdminEmail(email);
- case ADMIN_ONLY:
- return isAdminEmail(email);
- case MASTER_ONLY:
- AdminRole role = userService.getAdminUserRole(email);
- return role != null && role.equals(MASTER);
- default:
- throw new DomainException(ExceptionStatus.INVALID_STATUS);
- }
- }
+ /**
+ * 해당 토큰의 페이로드 정보가 인증 단계에 알맞는지 확인합니다.
+ *
+ * MASTER의 경우 현재 정적으로 관리하므로 이메일만 검증합니다.
+ *
+ *
+ * @param token 토큰
+ * @param authLevel 인증 단계
+ * @return 페이로드 정보가 실제 DB와 일치하면 true를 반환합니다.
+ */
+ public boolean isTokenAuthenticatable(String token, AuthLevel authLevel)
+ throws JsonProcessingException {
+ String email = getPayloadJson(token).get("email").asText();
+ if (email == null) {
+ throw new DomainException(ExceptionStatus.INVALID_ARGUMENT);
+ }
+ System.out.println("Hellowsdafasdf");
+ switch (authLevel) {
+ case USER_OR_ADMIN:
+ return true;
+ case USER_ONLY:
+ return !isAdminEmail(email);
+ case ADMIN_ONLY:
+ return isAdminEmail(email);
+ case MASTER_ONLY:
+ AdminRole role = userService.getAdminUserRole(email);
+ return role != null && role.equals(MASTER);
+ default:
+ throw new DomainException(ExceptionStatus.INVALID_STATUS);
+ }
+ }
- /**
- * 해당 이메일이 관리자 이메일인지 확인합니다.
- *
- * @param email 관리자 이메일
- * @return 관리자 이메일이면 true를 반환합니다.
- */
- private boolean isAdminEmail(String email) {
- return email.endsWith(masterProperties.getDomain())
- || email.endsWith(domainProperties.getAdminEmailDomain());
- }
+ /**
+ * 해당 이메일이 관리자 이메일인지 확인합니다.
+ *
+ * @param email 관리자 이메일
+ * @return 관리자 이메일이면 true를 반환합니다.
+ */
+ private boolean isAdminEmail(String email) {
+ // TODO : 이메일 검증 로직 수정 : 현재는 도메인만 검증하고 있어서 뚫릴 가능성이 있을듯, 추후 검토 필요
+ return email.endsWith(masterProperties.getDomain())
+ || email.endsWith(domainProperties.getAdminEmailDomain());
+ }
}
diff --git a/backend/src/main/java/org/ftclub/cabinet/auth/service/AuthFacadeService.java b/backend/src/main/java/org/ftclub/cabinet/auth/service/AuthFacadeService.java
index 7026403f9..f9670edfc 100644
--- a/backend/src/main/java/org/ftclub/cabinet/auth/service/AuthFacadeService.java
+++ b/backend/src/main/java/org/ftclub/cabinet/auth/service/AuthFacadeService.java
@@ -1,22 +1,24 @@
package org.ftclub.cabinet.auth.service;
-import org.ftclub.cabinet.config.ApiProperties;
-import org.ftclub.cabinet.dto.MasterLoginDto;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.time.LocalDateTime;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import org.ftclub.cabinet.config.ApiProperties;
+import org.ftclub.cabinet.dto.MasterLoginDto;
public interface AuthFacadeService {
void requestLoginToApi(HttpServletResponse res, ApiProperties apiProperties) throws IOException;
void handleLogin(String code, HttpServletRequest req, HttpServletResponse res,
- ApiProperties apiProperties, LocalDateTime now);
+ ApiProperties apiProperties, LocalDateTime now);
void masterLogin(MasterLoginDto masterLoginDto, HttpServletRequest req,
- HttpServletResponse res, LocalDateTime now);
+ HttpServletResponse res, LocalDateTime now);
void logout(HttpServletResponse res, ApiProperties apiProperties);
+
+ void handleTestLogin(HttpServletRequest req, ApiProperties apiProperties,
+ HttpServletResponse res, LocalDateTime now);
}
diff --git a/backend/src/main/java/org/ftclub/cabinet/auth/service/AuthFacadeServiceImpl.java b/backend/src/main/java/org/ftclub/cabinet/auth/service/AuthFacadeServiceImpl.java
index c1552c81b..cd2147986 100644
--- a/backend/src/main/java/org/ftclub/cabinet/auth/service/AuthFacadeServiceImpl.java
+++ b/backend/src/main/java/org/ftclub/cabinet/auth/service/AuthFacadeServiceImpl.java
@@ -1,6 +1,13 @@
package org.ftclub.cabinet.auth.service;
import com.fasterxml.jackson.databind.JsonNode;
+import java.io.IOException;
+import java.time.LocalDateTime;
+import java.util.HashMap;
+import java.util.Map;
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import org.ftclub.cabinet.auth.domain.CookieManager;
import org.ftclub.cabinet.auth.domain.TokenProvider;
@@ -9,15 +16,11 @@
import org.ftclub.cabinet.dto.MasterLoginDto;
import org.ftclub.cabinet.exception.ControllerException;
import org.ftclub.cabinet.exception.ExceptionStatus;
+import org.ftclub.cabinet.user.domain.UserRole;
+import org.ftclub.cabinet.user.repository.UserOptionalFetcher;
+import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
-import javax.servlet.http.Cookie;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import java.io.IOException;
-import java.time.LocalDateTime;
-import java.util.Map;
-
@Service
@RequiredArgsConstructor
public class AuthFacadeServiceImpl implements AuthFacadeService {
@@ -28,6 +31,9 @@ public class AuthFacadeServiceImpl implements AuthFacadeService {
private final AuthService authService;
private final OauthService oauthService;
+ private final UserOptionalFetcher userOptionalFetcher;
+
+
@Override
public void requestLoginToApi(HttpServletResponse res, ApiProperties apiProperties)
throws IOException {
@@ -36,20 +42,39 @@ public void requestLoginToApi(HttpServletResponse res, ApiProperties apiProperti
@Override
public void handleLogin(String code, HttpServletRequest req, HttpServletResponse res,
- ApiProperties apiProperties, LocalDateTime now) {
+ ApiProperties apiProperties, LocalDateTime now) {
String apiToken = oauthService.getTokenByCodeRequest(code, apiProperties);
JsonNode profile = oauthService.getProfileJsonByToken(apiToken, apiProperties);
Map claims = tokenProvider.makeClaimsByProviderProfile(
apiProperties.getProviderName(), profile);
authService.addUserIfNotExistsByClaims(claims);
String accessToken = tokenProvider.createToken(claims, now);
- Cookie cookie = cookieManager.cookieOf(tokenProvider.getTokenNameByProvider(apiProperties.getProviderName()), accessToken);
+ Cookie cookie = cookieManager.cookieOf(
+ tokenProvider.getTokenNameByProvider(apiProperties.getProviderName()), accessToken);
+ cookieManager.setCookieToClient(res, cookie, "/", req.getServerName());
+ }
+
+ @Override
+ public void handleTestLogin(HttpServletRequest req, ApiProperties apiProperties,
+ HttpServletResponse res, LocalDateTime now) {
+ Map claims = new HashMap<>();
+ claims.put("name",
+ "Test:" + userOptionalFetcher.findUsersByPartialName("Test:", Pageable.unpaged())
+ .getTotalElements());
+ claims.put("email", userOptionalFetcher.findUsersByPartialName("Test:", Pageable.unpaged())
+ .getTotalElements() + "Test@student.42seoul.kr");
+ claims.put("blackholedAt", null);
+ claims.put("role", UserRole.USER);
+ authService.addUserIfNotExistsByClaims(claims);
+ String accessToken = tokenProvider.createToken(claims, now);
+ Cookie cookie = cookieManager.cookieOf(
+ tokenProvider.getTokenNameByProvider(apiProperties.getProviderName()), accessToken);
cookieManager.setCookieToClient(res, cookie, "/", req.getServerName());
}
@Override
public void masterLogin(MasterLoginDto masterLoginDto, HttpServletRequest req,
- HttpServletResponse res, LocalDateTime now) {
+ HttpServletResponse res, LocalDateTime now) {
if (!authService.validateMasterLogin(masterLoginDto)) {
throw new ControllerException(ExceptionStatus.UNAUTHORIZED);
}
diff --git a/backend/src/main/java/org/ftclub/cabinet/auth/service/AuthService.java b/backend/src/main/java/org/ftclub/cabinet/auth/service/AuthService.java
index f46a7edf8..c5e0dd532 100644
--- a/backend/src/main/java/org/ftclub/cabinet/auth/service/AuthService.java
+++ b/backend/src/main/java/org/ftclub/cabinet/auth/service/AuthService.java
@@ -1,8 +1,8 @@
package org.ftclub.cabinet.auth.service;
-import java.time.LocalDate;
-import java.time.format.DateTimeFormatter;
-import java.time.format.DateTimeParseException;
+import static org.ftclub.cabinet.user.domain.UserRole.USER;
+
+import java.util.Map;
import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.ftclub.cabinet.config.DomainProperties;
@@ -12,14 +12,8 @@
import org.ftclub.cabinet.exception.ServiceException;
import org.ftclub.cabinet.user.service.UserService;
import org.ftclub.cabinet.utils.DateUtil;
-import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.stereotype.Service;
-import java.time.LocalDateTime;
-import java.util.Map;
-
-import static org.ftclub.cabinet.user.domain.UserRole.USER;
-
/**
* Cabi 자체의 인증 서비스입니다.
*/
@@ -57,8 +51,10 @@ public void addUserIfNotExistsByClaims(Map claims) {
if (blackHoledAtObject == null) {
userService.createUser(name, email, null, USER);
} else {
- userService.createUser(name, email, DateUtil.stringToDate(blackHoledAtObject.toString()), USER);
+ userService.createUser(name, email,
+ DateUtil.stringToDate(blackHoledAtObject.toString()), USER);
}
}
}
+
}
diff --git a/backend/src/main/java/org/ftclub/cabinet/cabinet/controller/CabinetController.java b/backend/src/main/java/org/ftclub/cabinet/cabinet/controller/CabinetController.java
index 7d7391e79..71a79d9e6 100644
--- a/backend/src/main/java/org/ftclub/cabinet/cabinet/controller/CabinetController.java
+++ b/backend/src/main/java/org/ftclub/cabinet/cabinet/controller/CabinetController.java
@@ -51,8 +51,7 @@ public List getBuildingFloorsResponse() {
public List getCabinetsPerSection(
@PathVariable("building") String building,
@PathVariable("floor") Integer floor) {
- log.info("Called getCabinetsPerSection");
- return cabinetFacadeService.getCabinetsPerSection(building, floor);
+ return cabinetFacadeService.getCabinetsPerSectionDSL(building, floor);
}
/**
diff --git a/backend/src/main/java/org/ftclub/cabinet/cabinet/domain/Cabinet.java b/backend/src/main/java/org/ftclub/cabinet/cabinet/domain/Cabinet.java
index e7707c9a4..a979beb2f 100644
--- a/backend/src/main/java/org/ftclub/cabinet/cabinet/domain/Cabinet.java
+++ b/backend/src/main/java/org/ftclub/cabinet/cabinet/domain/Cabinet.java
@@ -1,5 +1,24 @@
package org.ftclub.cabinet.cabinet.domain;
+import static org.ftclub.cabinet.exception.ExceptionStatus.INVALID_ARGUMENT;
+import static org.ftclub.cabinet.exception.ExceptionStatus.INVALID_STATUS;
+
+import java.util.List;
+import java.util.Objects;
+import javax.persistence.CascadeType;
+import javax.persistence.Column;
+import javax.persistence.Embedded;
+import javax.persistence.Entity;
+import javax.persistence.EnumType;
+import javax.persistence.Enumerated;
+import javax.persistence.FetchType;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.OneToMany;
+import javax.persistence.Table;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.NoArgsConstructor;
@@ -9,13 +28,6 @@
import org.ftclub.cabinet.lent.domain.LentHistory;
import org.ftclub.cabinet.utils.ExceptionUtil;
-import javax.persistence.*;
-import java.util.List;
-import java.util.Objects;
-
-import static org.ftclub.cabinet.exception.ExceptionStatus.INVALID_ARGUMENT;
-import static org.ftclub.cabinet.exception.ExceptionStatus.INVALID_STATUS;
-
/**
* 사물함 엔티티
*/
@@ -27,202 +39,198 @@
@Log4j2
public class Cabinet {
- @Id
- @GeneratedValue(strategy = GenerationType.IDENTITY)
- @Column(name = "CABINET_ID")
- private Long cabinetId;
-
- /**
- * 실물로 표시되는 번호입니다.
- */
- @Column(name = "VISIBLE_NUM")
- private Integer visibleNum;
-
- /**
- * {@link CabinetStatus}
- */
- @Enumerated(value = EnumType.STRING)
- @Column(name = "STATUS", length = 32, nullable = false)
- private CabinetStatus status;
-
- /**
- * {@link LentType}
- */
- @Enumerated(value = EnumType.STRING)
- @Column(name = "LENT_TYPE", length = 16, nullable = false)
- private LentType lentType;
-
- @Column(name = "MAX_USER", nullable = false)
- private Integer maxUser;
-
- /**
- * 사물함의 상태에 대한 메모입니다. 주로 고장 사유를 적습니다.
- */
- @Column(name = "STATUS_NOTE", length = 64)
- private String statusNote;
-
- /**
- * {@link Grid}
- */
- @Embedded
- private Grid grid;
-
- /**
- * 서비스에서 나타내지는 사물함의 제목입니다.
- */
- @Column(name = "TITLE", length = 64)
- private String title;
-
- /**
- * 서비스에서 나타내지는 사물함의 메모입니다.
- */
- @Column(name = "MEMO", length = 64)
- private String memo;
-
- /**
- * {@link CabinetPlace}
- */
- @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.PERSIST)
- @JoinColumn(name = "CABINET_PLACE_ID")
- private CabinetPlace cabinetPlace;
-
- @OneToMany(mappedBy = "cabinet",
- targetEntity = LentHistory.class,
- cascade = CascadeType.ALL,
- fetch = FetchType.LAZY)
- private List lentHistories;
-
- protected Cabinet(Integer visibleNum, CabinetStatus status, LentType lentType, Integer maxUser,
- Grid grid, CabinetPlace cabinetPlace) {
- this.visibleNum = visibleNum;
- this.status = status;
- this.lentType = lentType;
- this.maxUser = maxUser;
- this.grid = grid;
- this.cabinetPlace = cabinetPlace;
- this.title = "";
- this.memo = "";
- }
-
- public static Cabinet of(Integer visibleNum, CabinetStatus status, LentType lentType,
- Integer maxUser,
- Grid grid, CabinetPlace cabinetPlace) {
- Cabinet cabinet = new Cabinet(visibleNum, status, lentType, maxUser, grid, cabinetPlace);
- ExceptionUtil.throwIfFalse(cabinet.isValid(), new DomainException(INVALID_ARGUMENT));
- return cabinet;
- }
-
- private boolean isValid() {
- return (visibleNum >= 0 && maxUser >= 0 && grid != null && cabinetPlace != null
- && status != null && lentType != null);
- }
-
- public boolean isStatus(CabinetStatus cabinetStatus) {
- return this.status.equals(cabinetStatus);
- }
-
- public boolean isLentType(LentType lentType) {
- return this.lentType.equals(lentType);
- }
-
- public boolean isVisibleNum(Integer visibleNum) {
- return this.visibleNum.equals(visibleNum);
- }
-
- public boolean isCabinetPlace(CabinetPlace cabinetPlace) {
- return this.cabinetPlace.equals(cabinetPlace);
- }
-
- public void specifyCabinetPlace(CabinetPlace cabinetPlace) {
- log.info("setCabinetPlace : {}", cabinetPlace);
- this.cabinetPlace = cabinetPlace;
- }
-
- public void assignVisibleNum(Integer visibleNum) {
- log.info("assignVisibleNum : {}", visibleNum);
- this.visibleNum = visibleNum;
- ExceptionUtil.throwIfFalse(this.isValid(), new DomainException(INVALID_STATUS));
- }
-
- public void specifyStatus(CabinetStatus cabinetStatus) {
- log.info("specifyStatus : {}", cabinetStatus);
- this.status = cabinetStatus;
- ExceptionUtil.throwIfFalse(this.isValid(), new DomainException(INVALID_STATUS));
- }
-
- public void specifyMaxUser(Integer maxUser) {
- log.info("specifyMaxUser : {}", maxUser);
- this.maxUser = maxUser;
- ExceptionUtil.throwIfFalse(this.isValid(), new DomainException(INVALID_STATUS));
- }
-
- public void writeStatusNote(String statusNote) {
- log.info("writeStatusNote : {}", statusNote);
- this.statusNote = statusNote;
- ExceptionUtil.throwIfFalse(this.isValid(), new DomainException(INVALID_STATUS));
- }
-
- public void specifyLentType(LentType lentType) {
- log.info("specifyLentType : {}", lentType);
- this.lentType = lentType;
- ExceptionUtil.throwIfFalse(this.isValid(), new DomainException(INVALID_STATUS));
- }
-
- public void writeTitle(String title) {
- log.info("writeTitle : {}", title);
- this.title = title;
- ExceptionUtil.throwIfFalse(this.isValid(), new DomainException(INVALID_STATUS));
- }
-
- public void coordinateGrid(Grid grid) {
- log.info("coordinateGrid : {}", grid);
- this.grid = grid;
- ExceptionUtil.throwIfFalse(this.isValid(), new DomainException(INVALID_STATUS));
- }
-
- public void writeMemo(String memo) {
- this.memo = memo;
- ExceptionUtil.throwIfFalse(this.isValid(), new DomainException(INVALID_STATUS));
- }
-
- @Override
- public boolean equals(final Object other) {
- if (this == other) {
- return true;
- }
- if (!(other instanceof Cabinet)) {
- return false;
- }
- return this.cabinetId.equals(((Cabinet) other).cabinetId);
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(this.cabinetId);
- }
-
- /**
- * 대여 시작/종료에 따른 사용자의 수와 현재 상태에 따라 상태를 변경합니다.
- *
- * @param userCount 현재 사용자 수
- */
- public void specifyStatusByUserCount(Integer userCount) {
- log.info("specifyStatusByUserCount : {}", userCount);
- if (this.status.equals(CabinetStatus.BROKEN)) {
- throw new DomainException(INVALID_STATUS);
- }
- if (userCount.equals(0)) {
- this.status = CabinetStatus.AVAILABLE;
- return;
- }
- if (userCount.equals(this.maxUser)) {
- this.status = CabinetStatus.FULL;
- return;
- }
- if (0 < userCount && userCount < this.maxUser) {
- if (this.status.equals(CabinetStatus.FULL)) {
- this.status = CabinetStatus.LIMITED_AVAILABLE;
- }
- }
- }
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ @Column(name = "CABINET_ID")
+ private Long cabinetId;
+
+ /**
+ * 실물로 표시되는 번호입니다.
+ */
+ @Column(name = "VISIBLE_NUM")
+ private Integer visibleNum;
+
+ /**
+ * {@link CabinetStatus}
+ */
+ @Enumerated(value = EnumType.STRING)
+ @Column(name = "STATUS", length = 32, nullable = false)
+ private CabinetStatus status;
+
+ /**
+ * {@link LentType}
+ */
+ @Enumerated(value = EnumType.STRING)
+ @Column(name = "LENT_TYPE", length = 16, nullable = false)
+ private LentType lentType;
+
+ @Column(name = "MAX_USER", nullable = false)
+ private Integer maxUser;
+
+ /**
+ * 사물함의 상태에 대한 메모입니다. 주로 고장 사유를 적습니다.
+ */
+ @Column(name = "STATUS_NOTE", length = 64)
+ private String statusNote;
+
+ /**
+ * {@link Grid}
+ */
+ @Embedded
+ private Grid grid;
+
+ /**
+ * 서비스에서 나타내지는 사물함의 제목입니다.
+ */
+ @Column(name = "TITLE", length = 64)
+ private String title;
+
+ /**
+ * 서비스에서 나타내지는 사물함의 메모입니다.
+ */
+ @Column(name = "MEMO", length = 64)
+ private String memo;
+
+ /**
+ * {@link CabinetPlace}
+ */
+ @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.PERSIST)
+ @JoinColumn(name = "CABINET_PLACE_ID")
+ private CabinetPlace cabinetPlace;
+
+ @OneToMany(mappedBy = "cabinet",
+ targetEntity = LentHistory.class,
+ cascade = CascadeType.ALL,
+ fetch = FetchType.LAZY)
+ private List lentHistories;
+
+ protected Cabinet(Integer visibleNum, CabinetStatus status, LentType lentType, Integer maxUser,
+ Grid grid, CabinetPlace cabinetPlace) {
+ this.visibleNum = visibleNum;
+ this.status = status;
+ this.lentType = lentType;
+ this.maxUser = maxUser;
+ this.grid = grid;
+ this.cabinetPlace = cabinetPlace;
+ this.title = "";
+ this.memo = "";
+ }
+
+ public static Cabinet of(Integer visibleNum, CabinetStatus status, LentType lentType,
+ Integer maxUser,
+ Grid grid, CabinetPlace cabinetPlace) {
+ Cabinet cabinet = new Cabinet(visibleNum, status, lentType, maxUser, grid, cabinetPlace);
+ ExceptionUtil.throwIfFalse(cabinet.isValid(), new DomainException(INVALID_ARGUMENT));
+ return cabinet;
+ }
+
+ private boolean isValid() {
+ return (visibleNum >= 0 && maxUser >= 0 && grid != null && cabinetPlace != null
+ && status != null && lentType != null);
+ }
+
+ public boolean isStatus(CabinetStatus cabinetStatus) {
+ return this.status.equals(cabinetStatus);
+ }
+
+ public boolean isLentType(LentType lentType) {
+ return this.lentType.equals(lentType);
+ }
+
+ public boolean isVisibleNum(Integer visibleNum) {
+ return this.visibleNum.equals(visibleNum);
+ }
+
+ public boolean isCabinetPlace(CabinetPlace cabinetPlace) {
+ return this.cabinetPlace.equals(cabinetPlace);
+ }
+
+ public void specifyCabinetPlace(CabinetPlace cabinetPlace) {
+ log.info("setCabinetPlace : {}", cabinetPlace);
+ this.cabinetPlace = cabinetPlace;
+ }
+
+ public void assignVisibleNum(Integer visibleNum) {
+ log.info("assignVisibleNum : {}", visibleNum);
+ this.visibleNum = visibleNum;
+ ExceptionUtil.throwIfFalse(this.isValid(), new DomainException(INVALID_STATUS));
+ }
+
+ public void specifyStatus(CabinetStatus cabinetStatus) {
+ log.info("specifyStatus : {}", cabinetStatus);
+ this.status = cabinetStatus;
+ ExceptionUtil.throwIfFalse(this.isValid(), new DomainException(INVALID_STATUS));
+ }
+
+ public void specifyMaxUser(Integer maxUser) {
+ log.info("specifyMaxUser : {}", maxUser);
+ this.maxUser = maxUser;
+ ExceptionUtil.throwIfFalse(this.isValid(), new DomainException(INVALID_STATUS));
+ }
+
+ public void writeStatusNote(String statusNote) {
+ log.info("writeStatusNote : {}", statusNote);
+ this.statusNote = statusNote;
+ ExceptionUtil.throwIfFalse(this.isValid(), new DomainException(INVALID_STATUS));
+ }
+
+ public void specifyLentType(LentType lentType) {
+ log.info("specifyLentType : {}", lentType);
+ this.lentType = lentType;
+ ExceptionUtil.throwIfFalse(this.isValid(), new DomainException(INVALID_STATUS));
+ }
+
+ public void writeTitle(String title) {
+ log.info("writeTitle : {}", title);
+ this.title = title;
+ ExceptionUtil.throwIfFalse(this.isValid(), new DomainException(INVALID_STATUS));
+ }
+
+ public void coordinateGrid(Grid grid) {
+ log.info("coordinateGrid : {}", grid);
+ this.grid = grid;
+ ExceptionUtil.throwIfFalse(this.isValid(), new DomainException(INVALID_STATUS));
+ }
+
+ public void writeMemo(String memo) {
+ this.memo = memo;
+ ExceptionUtil.throwIfFalse(this.isValid(), new DomainException(INVALID_STATUS));
+ }
+
+ @Override
+ public boolean equals(final Object other) {
+ if (this == other) {
+ return true;
+ }
+ if (!(other instanceof Cabinet)) {
+ return false;
+ }
+ return this.cabinetId.equals(((Cabinet) other).cabinetId);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(this.cabinetId);
+ }
+
+ /**
+ * 대여 시작/종료에 따른 사용자의 수와 현재 상태에 따라 상태를 변경합니다.
+ *
+ * @param userCount 현재 사용자 수
+ */
+ public void specifyStatusByUserCount(Integer userCount) {
+ log.info("specifyStatusByUserCount : {}", userCount);
+ if (this.status.equals(CabinetStatus.BROKEN)) {
+ throw new DomainException(INVALID_STATUS);
+ }
+ if (userCount.equals(0)) {
+ this.status = CabinetStatus.PENDING;
+// this.status = CabinetStatus.AVAILABLE;
+ return;
+ }
+ if (userCount.equals(this.maxUser)) {
+ this.status = CabinetStatus.FULL;
+ return;
+ }
+ }
}
diff --git a/backend/src/main/java/org/ftclub/cabinet/cabinet/domain/CabinetPlace.java b/backend/src/main/java/org/ftclub/cabinet/cabinet/domain/CabinetPlace.java
index 4a244156e..e139fc017 100644
--- a/backend/src/main/java/org/ftclub/cabinet/cabinet/domain/CabinetPlace.java
+++ b/backend/src/main/java/org/ftclub/cabinet/cabinet/domain/CabinetPlace.java
@@ -45,6 +45,10 @@ public class CabinetPlace {
*/
@Embedded
private MapArea mapArea;
+ /* 양방향 매핑
+ @OneToMany(mappedBy = "cabinetPlace")
+ private List cabinets;
+*/
protected CabinetPlace(Location location, SectionFormation sectionFormation, MapArea mapArea) {
this.location = location;
diff --git a/backend/src/main/java/org/ftclub/cabinet/cabinet/domain/CabinetStatus.java b/backend/src/main/java/org/ftclub/cabinet/cabinet/domain/CabinetStatus.java
index 4cf712a0f..cb12a5579 100644
--- a/backend/src/main/java/org/ftclub/cabinet/cabinet/domain/CabinetStatus.java
+++ b/backend/src/main/java/org/ftclub/cabinet/cabinet/domain/CabinetStatus.java
@@ -14,12 +14,17 @@ public enum CabinetStatus {
*
* LIMITED_AVAILABLE : 만료기한이 설정되었으나 사용 가능
*
- * OVERDUE :연체됨
+ * OVERDUE : 연체됨
+ *
+ * PENDING : 다음 날 풀릴 사물함 상태
+ *
+ * IS_SESSION : 10분 동안 대여 대기 상태
*/
- BROKEN, AVAILABLE, FULL, LIMITED_AVAILABLE, OVERDUE;
+ BROKEN, AVAILABLE, FULL, LIMITED_AVAILABLE, OVERDUE, PENDING, IN_SESSION;
public boolean isValid() {
return this.equals(BROKEN) || this.equals(AVAILABLE) || this.equals(FULL) ||
- this.equals(LIMITED_AVAILABLE) || this.equals(OVERDUE);
+ this.equals(LIMITED_AVAILABLE) || this.equals(OVERDUE) || this.equals(PENDING)
+ || this.equals(IN_SESSION);
}
}
diff --git a/backend/src/main/java/org/ftclub/cabinet/cabinet/repository/CabinetComplexRepository.java b/backend/src/main/java/org/ftclub/cabinet/cabinet/repository/CabinetComplexRepository.java
new file mode 100644
index 000000000..9a4b03130
--- /dev/null
+++ b/backend/src/main/java/org/ftclub/cabinet/cabinet/repository/CabinetComplexRepository.java
@@ -0,0 +1,22 @@
+package org.ftclub.cabinet.cabinet.repository;
+
+import java.time.LocalDateTime;
+import java.util.List;
+import org.ftclub.cabinet.cabinet.domain.Cabinet;
+import org.ftclub.cabinet.cabinet.domain.CabinetPlace;
+import org.ftclub.cabinet.cabinet.domain.CabinetStatus;
+import org.ftclub.cabinet.dto.ActiveCabinetInfoEntities;
+import org.ftclub.cabinet.lent.domain.LentHistory;
+import org.ftclub.cabinet.user.domain.User;
+import org.ftclub.cabinet.utils.annotations.ComplexRepository;
+
+@ComplexRepository(entityClass = {Cabinet.class, CabinetPlace.class, LentHistory.class, User.class})
+public interface CabinetComplexRepository {
+
+ List findCabinetsActiveLentHistoriesByBuildingAndFloor(
+ String building, Integer floor);
+
+ List findAllCabinetsByBuildingAndFloor(String building, Integer floor);
+
+ List findAllCabinetsByCabinetStatusAndBeforeEndedAt(CabinetStatus cabinetStatus, LocalDateTime endedAt);
+}
diff --git a/backend/src/main/java/org/ftclub/cabinet/cabinet/repository/CabinetComplexRepositoryImpl.java b/backend/src/main/java/org/ftclub/cabinet/cabinet/repository/CabinetComplexRepositoryImpl.java
new file mode 100644
index 000000000..32f4f32d1
--- /dev/null
+++ b/backend/src/main/java/org/ftclub/cabinet/cabinet/repository/CabinetComplexRepositoryImpl.java
@@ -0,0 +1,82 @@
+package org.ftclub.cabinet.cabinet.repository;
+
+import static org.ftclub.cabinet.cabinet.domain.QCabinet.cabinet;
+import static org.ftclub.cabinet.cabinet.domain.QCabinetPlace.cabinetPlace;
+import static org.ftclub.cabinet.lent.domain.QLentHistory.lentHistory;
+import static org.ftclub.cabinet.user.domain.QUser.user;
+
+import com.querydsl.jpa.impl.JPAQuery;
+import com.querydsl.jpa.impl.JPAQueryFactory;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.util.List;
+import javax.persistence.EntityManager;
+import org.ftclub.cabinet.cabinet.domain.Cabinet;
+import org.ftclub.cabinet.cabinet.domain.CabinetStatus;
+import org.ftclub.cabinet.dto.ActiveCabinetInfoEntities;
+import org.ftclub.cabinet.dto.QActiveCabinetInfoEntities;
+import org.ftclub.cabinet.lent.domain.LentHistory;
+import org.springframework.cache.annotation.CacheConfig;
+import org.springframework.cache.annotation.Cacheable;
+
+//@CacheConfig(cacheNames = "cabinets")
+public class CabinetComplexRepositoryImpl implements CabinetComplexRepository {
+
+ private final JPAQueryFactory queryFactory;
+
+ public CabinetComplexRepositoryImpl(EntityManager em) {
+ this.queryFactory = new JPAQueryFactory(em);
+ }
+
+ // CACHE
+// @Cacheable(key = "#building + #floor")
+ public List findAllCabinetsByBuildingAndFloor(String building, Integer floor) {
+ JPAQuery query = queryFactory.selectFrom(cabinet)
+ .join(cabinetPlace)
+ .on(cabinet.cabinetPlace.cabinetPlaceId.eq(cabinetPlace.cabinetPlaceId))
+ .where(cabinetPlace.location.building
+ .eq(building)
+ .and(cabinetPlace.location.floor.eq(floor))
+ );
+ return query.fetch();
+ }
+
+
+ @Override
+ public List findCabinetsActiveLentHistoriesByBuildingAndFloor(
+ String building, Integer floor) {
+ return queryFactory.selectDistinct(
+ new QActiveCabinetInfoEntities(cabinet, lentHistory, user))
+ .from(cabinet)
+ .join(cabinetPlace)
+ .on(cabinet.cabinetPlace.cabinetPlaceId.eq(cabinetPlace.cabinetPlaceId))
+ .join(lentHistory)
+ .on(cabinet.cabinetId.eq(lentHistory.cabinet.cabinetId))
+ .join(user)
+ .on(lentHistory.user.userId.eq(user.userId))
+ .where(cabinetPlace.location.building
+ .eq(building)
+ .and(cabinetPlace.location.floor.eq(floor))
+ .and(lentHistory.endedAt.isNull())
+ )
+ .fetch();
+ }
+
+ @Override
+ public List findAllCabinetsByCabinetStatusAndBeforeEndedAt(CabinetStatus cabinetStatus,
+ LocalDateTime currentDate) {
+ //LentHistory 에서, 오늘날짜 이전의 endedAt이면서, 중복되지 않는 레코드 와 cabinet 을 join 해서 가져온다.
+ //cabinetStatus 는 PENDING 이어야한다.
+ return queryFactory.selectFrom(cabinet)
+ .join(lentHistory)
+ .on(cabinet.cabinetId.eq(lentHistory.cabinet.cabinetId))
+ .where(cabinet.status.eq(cabinetStatus)
+ .and(lentHistory.endedAt
+ .before(currentDate)
+// .before(LocalDateTime.from(LocalDate.now().atStartOfDay()))
+ )
+ ).fetch();
+ }
+
+
+}
diff --git a/backend/src/main/java/org/ftclub/cabinet/cabinet/repository/CabinetOptionalFetcher.java b/backend/src/main/java/org/ftclub/cabinet/cabinet/repository/CabinetOptionalFetcher.java
index 567f3e208..2c92e416b 100644
--- a/backend/src/main/java/org/ftclub/cabinet/cabinet/repository/CabinetOptionalFetcher.java
+++ b/backend/src/main/java/org/ftclub/cabinet/cabinet/repository/CabinetOptionalFetcher.java
@@ -1,5 +1,6 @@
package org.ftclub.cabinet.cabinet.repository;
+import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
@@ -52,6 +53,27 @@ public List findCabinetsActiveLentHistoriesByBuilding
}).collect(Collectors.toList());
}
+ public List findCabinetsActiveLentHistoriesByBuildingAndFloor2(
+ String building, Integer floor) {
+ return cabinetRepository.findCabinetsActiveLentHistoriesByBuildingAndFloor(building, floor);
+ }
+
+ public List findCabinetsByBuildingAndFloor2(String building, Integer floor) {
+ return cabinetRepository.findAllCabinetsByBuildingAndFloor(building, floor);
+ }
+
+ /**
+ * 유저 ID로 사물함을 찾습니다.
+ *
+ * @param userId 유저ID
+ * @return 사물함 엔티티
+ * @throws ServiceException 사물함을 찾을 수 없는 경우
+ */
+ public Cabinet findLentCabinetByUserId(Long userId) {
+ log.debug("Called findLentCabinetByUserId: {}", userId);
+ return cabinetRepository.findLentCabinetByUserId(userId).orElse(null);
+ }
+
public List findAllBuildings() {
log.debug("Called findAllBuildings");
return cabinetRepository.findAllBuildings();
@@ -68,6 +90,12 @@ public List findAllSectionsByBuildingAndFloor(String building, Integer f
return cabinetRepository.findAllSectionsByBuildingAndFloor(building, floor);
}
+ public List findAllPendingCabinetsByCabinetStatusAndBeforeEndedAt(CabinetStatus cabinetStatus,
+ LocalDateTime currentDate) {
+ log.debug("Called findAllCabinetsByCabinetStatusAndBeforeEndedAt: {}", cabinetStatus);
+ return cabinetRepository.findAllCabinetsByCabinetStatusAndBeforeEndedAt(cabinetStatus, currentDate);
+ }
+
public Page findPaginationByLentType(LentType lentType, PageRequest pageable) {
log.debug("Called findPaginationByLentType: {}", lentType);
return cabinetRepository.findPaginationByLentType(lentType, pageable);
@@ -93,17 +121,6 @@ public List findAllCabinetsByBuildingAndFloor(String building, Integer
}
/*-------------------------------------------GET--------------------------------------------*/
- /**
- * 유저 ID로 사물함을 찾습니다.
- *
- * @param userId 유저ID
- * @return 사물함 엔티티
- * @throws ServiceException 사물함을 찾을 수 없는 경우
- */
- public Cabinet findLentCabinetByUserId(Long userId) {
- log.debug("Called findLentCabinetByUserId: {}", userId);
- return cabinetRepository.findLentCabinetByUserId(userId).orElse(null);
- }
/**
* 사물함 ID로 변경 사항이 예정된 사물함을 찾습니다.
diff --git a/backend/src/main/java/org/ftclub/cabinet/cabinet/repository/CabinetRepository.java b/backend/src/main/java/org/ftclub/cabinet/cabinet/repository/CabinetRepository.java
index 8ac9515fe..4a6c13fa7 100644
--- a/backend/src/main/java/org/ftclub/cabinet/cabinet/repository/CabinetRepository.java
+++ b/backend/src/main/java/org/ftclub/cabinet/cabinet/repository/CabinetRepository.java
@@ -17,7 +17,7 @@
import org.springframework.stereotype.Repository;
@Repository
-public interface CabinetRepository extends JpaRepository {
+public interface CabinetRepository extends JpaRepository, CabinetComplexRepository {
@Lock(LockModeType.PESSIMISTIC_WRITE)
@Query("SELECT c "
@@ -68,19 +68,19 @@ List findAllSectionsByBuildingAndFloor(
"FROM Cabinet c " +
"WHERE c.lentType = :lentType")
Page findPaginationByLentType(@Param("lentType") LentType lentType,
- Pageable pageable);
+ Pageable pageable);
@Query("SELECT c " +
"FROM Cabinet c " +
"WHERE c.status = :status")
Page findPaginationByStatus(@Param("status") CabinetStatus status,
- Pageable pageable);
+ Pageable pageable);
@Query("SELECT c " +
"FROM Cabinet c " +
"WHERE c.visibleNum = :visibleNum")
Page findPaginationByVisibleNum(@Param("visibleNum") Integer visibleNum,
- Pageable pageable);
+ Pageable pageable);
@Query("SELECT c " +
"FROM Cabinet c " +
@@ -92,7 +92,8 @@ Page findPaginationByVisibleNum(@Param("visibleNum") Integer visibleNum
"FROM Cabinet c " +
"JOIN c.lentHistories lh ON lh.cabinetId = c.cabinetId " +
"JOIN lh.user u ON lh.userId = u.userId " +
- "WHERE c.cabinetPlace.location.building = :building AND c.cabinetPlace.location.floor = :floor " +
+ "WHERE c.cabinetPlace.location.building = :building AND c.cabinetPlace.location.floor = :floor "
+ +
"AND lh.endedAt IS NULL")
List