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 71a79d9e6..4bed18d30 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 @@ -8,6 +8,7 @@ import org.ftclub.cabinet.cabinet.service.CabinetFacadeService; import org.ftclub.cabinet.dto.BuildingFloorsDto; import org.ftclub.cabinet.dto.CabinetInfoResponseDto; +import org.ftclub.cabinet.dto.CabinetPendingResponseDto; import org.ftclub.cabinet.dto.CabinetsPerSectionResponseDto; import org.ftclub.cabinet.exception.ControllerException; import org.springframework.web.bind.annotation.GetMapping; @@ -68,4 +69,16 @@ public CabinetInfoResponseDto getCabinetInfo( log.info("Called getCabinetInfo {}", cabinetId); return cabinetFacadeService.getCabinetInfo(cabinetId); } + + /** + * 오픈 예정인 사물함들의 정보를 가져옵니다. + * + * @return 오픈 예정인 사물함들의 정보를 반환합니다. + */ + @GetMapping("/pending") + @AuthGuard(level = AuthLevel.USER_OR_ADMIN) + public CabinetPendingResponseDto getPendingCabinets() { + log.info("Called getPendingCabinets"); + return cabinetFacadeService.getPendingCabinets(); + } } 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 2c92e416b..db75da8ef 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 @@ -29,166 +29,184 @@ @Transactional public class CabinetOptionalFetcher { - private final CabinetRepository cabinetRepository; - private final CabinetMapper cabinetMapper; - - /*-------------------------------------------FIND-------------------------------------------*/ - - public Cabinet findCabinet(Long cabinetId) { - log.debug("Called findCabinet: {}", cabinetId); - return cabinetRepository.findById(cabinetId).orElse(null); - } - - public List findCabinetsActiveLentHistoriesByBuildingAndFloor( - String building, Integer floor) { - log.debug("Called findCabinetsActiveLentHistoriesByBuildingAndFloor: {}, {}", building, - floor); - return cabinetRepository.findCabinetActiveLentHistoryUserListByBuildingAndFloor(building, - floor).stream() - .map(result -> { - Cabinet cabinet = (Cabinet) result[0]; - LentHistory lentHistory = (LentHistory) result[1]; - User user = (User) result[2]; - return cabinetMapper.toActiveCabinetInfoEntitiesDto(cabinet, lentHistory, user); - }).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(); - } - - public List findAllFloorsByBuilding(String building) { - log.debug("Called findAllFloorsByBuilding: {}", building); - return cabinetRepository.findAllFloorsByBuilding(building); - } - - // deprecated - public List findAllSectionsByBuildingAndFloor(String building, Integer floor) { - log.debug("Called findAllSectionsByBuildingAndFloor: {}, {}", building, floor); - 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); - } - - public Page findPaginationByStatus(CabinetStatus status, PageRequest pageable) { - log.debug("Called findPaginationByStatus: {}", status); - return cabinetRepository.findPaginationByStatus(status, pageable); - } - - public Page findPaginationByVisibleNum(Integer visibleNum, PageRequest pageable) { - log.debug("Called findPaginationByVisibleNum: {}", visibleNum); - return cabinetRepository.findPaginationByVisibleNum(visibleNum, pageable); - } - - public List findAllCabinetsByLocation(Location location) { - log.debug("Called findAllCabinetsByLocation: {}", location); - return cabinetRepository.findAllCabinetsByLocation(location); - } - - public List findAllCabinetsByBuildingAndFloor(String building, Integer floor) { - return cabinetRepository.findAllByBuildingAndFloor(building, floor); - } - /*-------------------------------------------GET--------------------------------------------*/ - - - /** - * 사물함 ID로 변경 사항이 예정된 사물함을 찾습니다. - *

- * X Lock을 획득한 상태로 가져옵니다. - * - * @param cabinetId 사물함 ID - * @return 사물함 엔티티 - * @throws ServiceException 사물함을 찾을 수 없는 경우 - */ - public Cabinet getCabinetForUpdate(Long cabinetId) { - log.debug("Called getCabinetForUpdate: {}", cabinetId); - return cabinetRepository.findByIdForUpdate(cabinetId) - .orElseThrow(() -> new ServiceException(ExceptionStatus.NOT_FOUND_CABINET)); - } - - /** - * 사물함 ID로 사물함을 찾습니다. - * - * @param cabinetId 사물함 ID - * @return 사물함 엔티티 - * @throws ServiceException 사물함을 찾을 수 없는 경우 - */ - public Cabinet getCabinet(Long cabinetId) { - log.debug("Called getCabinet: {}", cabinetId); - return cabinetRepository.findById(cabinetId) - .orElseThrow(() -> new ServiceException(ExceptionStatus.NOT_FOUND_CABINET)); - } - - /** - * 유저 ID로 사물함을 찾습니다. - * - * @param userId 유저ID - * @return 사물함 엔티티 - * @throws ServiceException 사물함을 찾을 수 없는 경우 - */ - public Cabinet getLentCabinetByUserId(Long userId) { - log.debug("Called getLentCabinetByUserId: {}", userId); - return cabinetRepository.findLentCabinetByUserId(userId) - .orElseThrow(() -> new ServiceException(ExceptionStatus.NOT_FOUND_CABINET)); - } - - /** - * 사물함 ID로 동아리 사물함을 찾습니다. - * - * @param cabinetId 사물함 ID - * @return 동아리 사물함 엔티티 - * @throws ServiceException 사물함을 찾을 수 없는 경우 - */ - public Cabinet getClubCabinet(Long cabinetId) { - log.debug("Called getClubCabinet: {}", cabinetId); - Cabinet cabinet = getCabinet(cabinetId); - if (!cabinet.isLentType(LentType.CLUB)) { - throw new ServiceException(ExceptionStatus.NOT_FOUND_CABINET); - } - return cabinet; - } - - /** - * 사물함 ID로 위치(빌딩, 층, 섹션) 정보를 찾습니다. - * - * @param cabinetId 사물함 ID - * @return 위치 엔티티 - * @throws ServiceException 사물함을 찾을 수 없는 경우 - */ - public Location getLocation(Long cabinetId) { - log.debug("Called getLocation: {}", cabinetId); - return cabinetRepository.findLocationById(cabinetId) - .orElseThrow(() -> new ServiceException(ExceptionStatus.NOT_FOUND_CABINET)); - } + private final CabinetRepository cabinetRepository; + private final CabinetMapper cabinetMapper; + + /*-------------------------------------------FIND-------------------------------------------*/ + + public Cabinet findCabinet(Long cabinetId) { + log.debug("Called findCabinet: {}", cabinetId); + return cabinetRepository.findById(cabinetId).orElse(null); + } + + public List findCabinetsActiveLentHistoriesByBuildingAndFloor( + String building, Integer floor) { + log.debug("Called findCabinetsActiveLentHistoriesByBuildingAndFloor: {}, {}", building, + floor); + return cabinetRepository.findCabinetActiveLentHistoryUserListByBuildingAndFloor(building, + floor).stream() + .map(result -> { + Cabinet cabinet = (Cabinet) result[0]; + LentHistory lentHistory = (LentHistory) result[1]; + User user = (User) result[2]; + return cabinetMapper.toActiveCabinetInfoEntitiesDto(cabinet, lentHistory, user); + }).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(); + } + + public List findAllFloorsByBuilding(String building) { + log.debug("Called findAllFloorsByBuilding: {}", building); + return cabinetRepository.findAllFloorsByBuilding(building); + } + + // deprecated + public List findAllSectionsByBuildingAndFloor(String building, Integer floor) { + log.debug("Called findAllSectionsByBuildingAndFloor: {}, {}", building, floor); + 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); + } + + public Page findPaginationByStatus(CabinetStatus status, PageRequest pageable) { + log.debug("Called findPaginationByStatus: {}", status); + return cabinetRepository.findPaginationByStatus(status, pageable); + } + + public Page findPaginationByVisibleNum(Integer visibleNum, PageRequest pageable) { + log.debug("Called findPaginationByVisibleNum: {}", visibleNum); + return cabinetRepository.findPaginationByVisibleNum(visibleNum, pageable); + } + + public List findAllCabinetsByLocation(Location location) { + log.debug("Called findAllCabinetsByLocation: {}", location); + return cabinetRepository.findAllCabinetsByLocation(location); + } + + public List findAllCabinetsByBuildingAndFloor(String building, Integer floor) { + return cabinetRepository.findAllByBuildingAndFloor(building, floor); + } + /*-------------------------------------------GET--------------------------------------------*/ + + + /** + * 사물함 ID로 변경 사항이 예정된 사물함을 찾습니다. + *

+ * X Lock을 획득한 상태로 가져옵니다. + * + * @param cabinetId 사물함 ID + * @return 사물함 엔티티 + * @throws ServiceException 사물함을 찾을 수 없는 경우 + */ + public Cabinet getCabinetForUpdate(Long cabinetId) { + log.debug("Called getCabinetForUpdate: {}", cabinetId); + return cabinetRepository.findByIdForUpdate(cabinetId) + .orElseThrow(() -> new ServiceException(ExceptionStatus.NOT_FOUND_CABINET)); + } + + /** + * 사물함 ID로 사물함을 찾습니다. + * + * @param cabinetId 사물함 ID + * @return 사물함 엔티티 + * @throws ServiceException 사물함을 찾을 수 없는 경우 + */ + public Cabinet getCabinet(Long cabinetId) { + log.debug("Called getCabinet: {}", cabinetId); + return cabinetRepository.findById(cabinetId) + .orElseThrow(() -> new ServiceException(ExceptionStatus.NOT_FOUND_CABINET)); + } + + /** + * 유저 ID로 사물함을 찾습니다. + * + * @param userId 유저ID + * @return 사물함 엔티티 + * @throws ServiceException 사물함을 찾을 수 없는 경우 + */ + public Cabinet getLentCabinetByUserId(Long userId) { + log.debug("Called getLentCabinetByUserId: {}", userId); + return cabinetRepository.findLentCabinetByUserId(userId) + .orElseThrow(() -> new ServiceException(ExceptionStatus.NOT_FOUND_CABINET)); + } + + /** + * 사물함 ID로 동아리 사물함을 찾습니다. + * + * @param cabinetId 사물함 ID + * @return 동아리 사물함 엔티티 + * @throws ServiceException 사물함을 찾을 수 없는 경우 + */ + public Cabinet getClubCabinet(Long cabinetId) { + log.debug("Called getClubCabinet: {}", cabinetId); + Cabinet cabinet = getCabinet(cabinetId); + if (!cabinet.isLentType(LentType.CLUB)) { + throw new ServiceException(ExceptionStatus.NOT_FOUND_CABINET); + } + return cabinet; + } + + /** + * 사물함 ID로 위치(빌딩, 층, 섹션) 정보를 찾습니다. + * + * @param cabinetId 사물함 ID + * @return 위치 엔티티 + * @throws ServiceException 사물함을 찾을 수 없는 경우 + */ + public Location getLocation(Long cabinetId) { + log.debug("Called getLocation: {}", cabinetId); + return cabinetRepository.findLocationById(cabinetId) + .orElseThrow(() -> new ServiceException(ExceptionStatus.NOT_FOUND_CABINET)); + } + + /** + * 충별로 오픈 예정인 사물함들을 찾습니다. + * @param floor 층 + * @return 오픈 예정인 사물함들의 ID 리스트 + */ + + public List findPendingCabinets(Integer floor) { + log.debug("Called findPendingCabinets"); + return cabinetRepository.findPendingCabinets(floor).orElse(null); + } + + public List findAvailableCabinets(Integer floor) { + log.debug("Called findAvailableCabinets"); + return cabinetRepository.findAvailableCabinets(floor).orElse(null); + } } 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 4a6c13fa7..dfd7a2d29 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 @@ -104,4 +104,14 @@ List findCabinetActiveLentHistoryUserListByBuildingAndFloor( "WHERE c.cabinetPlace.location.building = :building AND c.cabinetPlace.location.floor = :floor") List findAllByBuildingAndFloor(@Param("building") String building, @Param("floor") Integer floor); + + @Query("SELECT c.cabinetId " + + "FROM Cabinet c " + + "WHERE c.status = org.ftclub.cabinet.cabinet.domain.CabinetStatus.PENDING AND c.cabinetPlace.location.floor = :floor") + Optional> findPendingCabinets(@Param("floor") Integer floor); + + @Query("SELECT c.cabinetId " + + "FROM Cabinet c " + + "WHERE c.status = org.ftclub.cabinet.cabinet.domain.CabinetStatus.AVAILABLE AND c.cabinetPlace.location.floor = :floor") + Optional> findAvailableCabinets(@Param("floor") Integer floor); } diff --git a/backend/src/main/java/org/ftclub/cabinet/cabinet/service/CabinetFacadeService.java b/backend/src/main/java/org/ftclub/cabinet/cabinet/service/CabinetFacadeService.java index 0e7138ab6..1c1c19a89 100644 --- a/backend/src/main/java/org/ftclub/cabinet/cabinet/service/CabinetFacadeService.java +++ b/backend/src/main/java/org/ftclub/cabinet/cabinet/service/CabinetFacadeService.java @@ -8,6 +8,7 @@ import org.ftclub.cabinet.dto.CabinetInfoPaginationDto; import org.ftclub.cabinet.dto.CabinetInfoResponseDto; import org.ftclub.cabinet.dto.CabinetPaginationDto; +import org.ftclub.cabinet.dto.CabinetPendingResponseDto; import org.ftclub.cabinet.dto.CabinetSimplePaginationDto; import org.ftclub.cabinet.dto.CabinetStatusRequestDto; import org.ftclub.cabinet.dto.CabinetsPerSectionResponseDto; @@ -53,6 +54,7 @@ List getCabinetsPerSectionRefactor(String buildin Integer floor); List getCabinetsPerSectionDSL(String building, Integer floor); + /** * 사물함의 상태 메모를 업데이트합니다. * @@ -106,8 +108,8 @@ List getCabinetsPerSectionRefactor(String buildin * 대여 타입에 따른 사물함 페이지네이션을 가져옵니다. * * @param lentType 대여 타입 - * @param page 페이지 번호 - * @param size 페이지 당 보여줄 개수 + * @param page 페이지 번호 + * @param size 페이지 당 보여줄 개수 * @return 사물함 페이지네이션 */ CabinetPaginationDto getCabinetPaginationByLentType(LentType lentType, Integer page, @@ -116,9 +118,9 @@ CabinetPaginationDto getCabinetPaginationByLentType(LentType lentType, Integer p /** * 사물함 상태에 따른 사물함 페이지네이션을 가져옵니다. * - * @param status 사물함 상태 - * @param page 페이지 번호 - * @param size 페이지 당 보여줄 개수 + * @param status 사물함 상태 + * @param page 페이지 번호 + * @param size 페이지 당 보여줄 개수 * @return 사물함 페이지네이션 */ CabinetPaginationDto getCabinetPaginationByStatus(CabinetStatus status, Integer page, @@ -128,8 +130,8 @@ CabinetPaginationDto getCabinetPaginationByStatus(CabinetStatus status, Integer * 사물함 표시 번호에 따른 사물함 페이지네이션을 가져옵니다. * * @param visibleNum 사물함 표시 번호 - * @param page 페이지 번호 - * @param size 페이지 당 보여줄 개수 + * @param page 페이지 번호 + * @param size 페이지 당 보여줄 개수 * @return 사물함 페이지네이션 */ CabinetPaginationDto getCabinetPaginationByVisibleNum(Integer visibleNum, Integer page, @@ -139,7 +141,7 @@ CabinetPaginationDto getCabinetPaginationByVisibleNum(Integer visibleNum, Intege * 사물함 Id에 따른 대여 기록 페이지네이션을 가져옵니다. * * @param cabinetId 사물함 Id - * @param page 페이지네이션(page, size) + * @param page 페이지네이션(page, size) * @return 대여 기록 페이지네이션 */ LentHistoryPaginationDto getCabinetLentHistoriesPagination(Long cabinetId, @@ -147,10 +149,15 @@ LentHistoryPaginationDto getCabinetLentHistoriesPagination(Long cabinetId, Integer size); /** - * 사물함에 동아 - * * @param clubStatusRequestDto */ void updateCabinetClubStatus(CabinetClubStatusRequestDto clubStatusRequestDto); + /** + * 오픈 예정인 사물함 정보를 층별로 가져옵니다. + * + * @return 오픈 예정인 사물함 정보 + */ + CabinetPendingResponseDto getPendingCabinets(); + } diff --git a/backend/src/main/java/org/ftclub/cabinet/cabinet/service/CabinetFacadeServiceImpl.java b/backend/src/main/java/org/ftclub/cabinet/cabinet/service/CabinetFacadeServiceImpl.java index e88cef02f..6bf8ba510 100644 --- a/backend/src/main/java/org/ftclub/cabinet/cabinet/service/CabinetFacadeServiceImpl.java +++ b/backend/src/main/java/org/ftclub/cabinet/cabinet/service/CabinetFacadeServiceImpl.java @@ -21,6 +21,7 @@ import org.ftclub.cabinet.dto.CabinetInfoPaginationDto; import org.ftclub.cabinet.dto.CabinetInfoResponseDto; import org.ftclub.cabinet.dto.CabinetPaginationDto; +import org.ftclub.cabinet.dto.CabinetPendingResponseDto; import org.ftclub.cabinet.dto.CabinetPreviewDto; import org.ftclub.cabinet.dto.CabinetSimpleDto; import org.ftclub.cabinet.dto.CabinetSimplePaginationDto; @@ -398,7 +399,36 @@ private List generateLentHistoryDtoList( .collect(Collectors.toList()); } - /*--------------------------------------------CUD--------------------------------------------*/ + /** + * {@inheritDoc} + */ + @Override + @Transactional + public CabinetPendingResponseDto getPendingCabinets() { + log.debug("getPendingCabinets"); + List> cabinetPreviewDtos = new ArrayList<>(); + for (int i = 2; i <= 5; i++) { + List cabinetPreviewDtoList = new ArrayList<>(); + // pending 상태인 사물함들의 cabinetId를 가져온다. + List pendingCabinetsIdByFloor = cabinetOptionalFetcher.findPendingCabinets(i); + // 순회를 돌면서 cabinetPreviewDto를 가져온다. + for (Long pendingCabinetId : pendingCabinetsIdByFloor) { + cabinetPreviewDtoList.add(cabinetMapper.toCabinetPreviewDto(cabinetOptionalFetcher.findCabinet(pendingCabinetId), + 0, "")); + } + // available 상태인 사물함들의 cabinetId를 가져온다. + List availableCabinetsIdByFloor = cabinetOptionalFetcher.findAvailableCabinets(i); + for (Long availableCabinetId : availableCabinetsIdByFloor) { + cabinetPreviewDtoList.add(cabinetMapper.toCabinetPreviewDto(cabinetOptionalFetcher.findCabinet(availableCabinetId), + 0, "")); + } + cabinetPreviewDtos.add(cabinetPreviewDtoList); + } + + return new CabinetPendingResponseDto(cabinetPreviewDtos); + } + + /*--------------------------------------------CUD--------------------------------------------*/ /** * {@inheritDoc} diff --git a/backend/src/main/java/org/ftclub/cabinet/cabinet/service/CabinetService.java b/backend/src/main/java/org/ftclub/cabinet/cabinet/service/CabinetService.java index 6e291387b..247688aac 100644 --- a/backend/src/main/java/org/ftclub/cabinet/cabinet/service/CabinetService.java +++ b/backend/src/main/java/org/ftclub/cabinet/cabinet/service/CabinetService.java @@ -4,6 +4,9 @@ import org.ftclub.cabinet.cabinet.domain.CabinetStatus; import org.ftclub.cabinet.cabinet.domain.Grid; import org.ftclub.cabinet.cabinet.domain.LentType; +import org.ftclub.cabinet.dto.CabinetInfoResponseDto; + +import java.util.List; public interface CabinetService { diff --git a/backend/src/main/java/org/ftclub/cabinet/cabinet/service/CabinetServiceImpl.java b/backend/src/main/java/org/ftclub/cabinet/cabinet/service/CabinetServiceImpl.java index dafc83f52..280c78405 100644 --- a/backend/src/main/java/org/ftclub/cabinet/cabinet/service/CabinetServiceImpl.java +++ b/backend/src/main/java/org/ftclub/cabinet/cabinet/service/CabinetServiceImpl.java @@ -9,6 +9,7 @@ import org.ftclub.cabinet.cabinet.domain.LentType; import org.ftclub.cabinet.cabinet.repository.CabinetOptionalFetcher; import org.ftclub.cabinet.config.CabinetProperties; +import org.ftclub.cabinet.dto.CabinetInfoResponseDto; import org.ftclub.cabinet.exception.ExceptionStatus; import org.ftclub.cabinet.exception.ServiceException; import org.ftclub.cabinet.lent.repository.LentOptionalFetcher; @@ -16,6 +17,9 @@ import org.springframework.stereotype.Service; import org.springframework.util.StringUtils; +import java.util.ArrayList; +import java.util.List; + @Service @RequiredArgsConstructor @Transactional diff --git a/backend/src/main/java/org/ftclub/cabinet/dto/CabinetPendingResponseDto.java b/backend/src/main/java/org/ftclub/cabinet/dto/CabinetPendingResponseDto.java new file mode 100644 index 000000000..cc2a0f18e --- /dev/null +++ b/backend/src/main/java/org/ftclub/cabinet/dto/CabinetPendingResponseDto.java @@ -0,0 +1,14 @@ +package org.ftclub.cabinet.dto; + +import java.util.List; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.ToString; + +@AllArgsConstructor +@Getter +@ToString +public class CabinetPendingResponseDto { + + private final List> cabinetInfoResponseDtos; +} diff --git a/backend/src/main/java/org/ftclub/cabinet/dto/MyProfileResponseDto.java b/backend/src/main/java/org/ftclub/cabinet/dto/MyProfileResponseDto.java index 141197781..08ada145b 100644 --- a/backend/src/main/java/org/ftclub/cabinet/dto/MyProfileResponseDto.java +++ b/backend/src/main/java/org/ftclub/cabinet/dto/MyProfileResponseDto.java @@ -3,6 +3,7 @@ import java.time.LocalDateTime; import lombok.AllArgsConstructor; import lombok.Getter; +import org.ftclub.cabinet.user.domain.LentExtension; /** * 내 프로필 정보와 대여 중인 사물함의 ID를 반환하는 DTO입니다. @@ -15,5 +16,5 @@ public class MyProfileResponseDto { private final String name; private final Long cabinetId; private final LocalDateTime unbannedAt; - private final boolean extensible; + private final LentExtensionResponseDto lentExtensionResponseDto; } diff --git a/backend/src/main/java/org/ftclub/cabinet/mapper/UserMapper.java b/backend/src/main/java/org/ftclub/cabinet/mapper/UserMapper.java index 8d9bcca88..da11e80e6 100644 --- a/backend/src/main/java/org/ftclub/cabinet/mapper/UserMapper.java +++ b/backend/src/main/java/org/ftclub/cabinet/mapper/UserMapper.java @@ -36,9 +36,10 @@ public interface UserMapper { UserProfileDto toUserProfileDto(User user); @Mapping(target = "userId", source = "user.userId") + @Mapping(target = "name", source = "user.name") @Mapping(target = "cabinetId", source = "cabinet.cabinetId") MyProfileResponseDto toMyProfileResponseDto(UserSessionDto user, Cabinet cabinet, - BanHistory banHistory, boolean extensible); + BanHistory banHistory, LentExtensionResponseDto lentExtensionResponseDto); BlockedUserPaginationDto toBlockedUserPaginationDto(List result, Long totalLength); diff --git a/backend/src/main/java/org/ftclub/cabinet/user/controller/UserController.java b/backend/src/main/java/org/ftclub/cabinet/user/controller/UserController.java index c5487b537..ea9eecc90 100644 --- a/backend/src/main/java/org/ftclub/cabinet/user/controller/UserController.java +++ b/backend/src/main/java/org/ftclub/cabinet/user/controller/UserController.java @@ -62,7 +62,7 @@ public LentExtensionPaginationDto getMyLentExtension( public LentExtensionPaginationDto getMyActiveLentExtension( @UserSession UserSessionDto userSessionDto) { log.info("Called getMyActiveLentExtension: {}", userSessionDto.getName()); - return userFacadeService.getMyActiveLentExtension(userSessionDto); + return userFacadeService.getMyActiveLentExtensionPage(userSessionDto); } /** diff --git a/backend/src/main/java/org/ftclub/cabinet/user/repository/LentExtensionOptionalFetcher.java b/backend/src/main/java/org/ftclub/cabinet/user/repository/LentExtensionOptionalFetcher.java index a83344b59..7c391f09d 100644 --- a/backend/src/main/java/org/ftclub/cabinet/user/repository/LentExtensionOptionalFetcher.java +++ b/backend/src/main/java/org/ftclub/cabinet/user/repository/LentExtensionOptionalFetcher.java @@ -3,8 +3,6 @@ import java.util.List; import lombok.RequiredArgsConstructor; import lombok.extern.log4j.Log4j2; -import org.ftclub.cabinet.exception.ExceptionStatus; -import org.ftclub.cabinet.exception.ServiceException; import org.ftclub.cabinet.user.domain.LentExtension; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; @@ -33,4 +31,9 @@ public Page findAllNotExpired(PageRequest pageable) { public List findLentExtensionByUserId(Long userId) { return lentExtensionRepository.findAllByUserId(userId); } + + @Transactional(readOnly = true) + public LentExtension findActiveLentExtensionByUserId(Long userId) { + return lentExtensionRepository.findByUserId(userId); + } } diff --git a/backend/src/main/java/org/ftclub/cabinet/user/repository/LentExtensionRepository.java b/backend/src/main/java/org/ftclub/cabinet/user/repository/LentExtensionRepository.java index 387f02d63..642113434 100644 --- a/backend/src/main/java/org/ftclub/cabinet/user/repository/LentExtensionRepository.java +++ b/backend/src/main/java/org/ftclub/cabinet/user/repository/LentExtensionRepository.java @@ -1,7 +1,6 @@ package org.ftclub.cabinet.user.repository; import java.util.List; -import java.util.Optional; import org.ftclub.cabinet.user.domain.LentExtension; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; @@ -26,4 +25,6 @@ public interface LentExtensionRepository extends JpaRepository findAllByUserId(@Param("userId") Long userId); + + LentExtension findByUserId(@Param("userId") Long userId); } diff --git a/backend/src/main/java/org/ftclub/cabinet/user/service/LentExtensionService.java b/backend/src/main/java/org/ftclub/cabinet/user/service/LentExtensionService.java index f0a900bcb..03ea19898 100644 --- a/backend/src/main/java/org/ftclub/cabinet/user/service/LentExtensionService.java +++ b/backend/src/main/java/org/ftclub/cabinet/user/service/LentExtensionService.java @@ -1,5 +1,7 @@ package org.ftclub.cabinet.user.service; +import java.util.List; +import org.ftclub.cabinet.dto.LentExtensionResponseDto; import org.ftclub.cabinet.dto.UserSessionDto; public interface LentExtensionService { @@ -12,4 +14,6 @@ public interface LentExtensionService { void assignLentExtension(String username); + List getActiveLentExtensionList(UserSessionDto userSessionDto); + } diff --git a/backend/src/main/java/org/ftclub/cabinet/user/service/LentExtensionServiceImpl.java b/backend/src/main/java/org/ftclub/cabinet/user/service/LentExtensionServiceImpl.java index 70f8e35af..a7f2794c3 100644 --- a/backend/src/main/java/org/ftclub/cabinet/user/service/LentExtensionServiceImpl.java +++ b/backend/src/main/java/org/ftclub/cabinet/user/service/LentExtensionServiceImpl.java @@ -7,11 +7,14 @@ import lombok.RequiredArgsConstructor; import lombok.extern.log4j.Log4j2; import org.ftclub.cabinet.config.CabinetProperties; +import org.ftclub.cabinet.dto.LentExtensionResponseDto; import org.ftclub.cabinet.dto.UserMonthDataDto; +import org.ftclub.cabinet.dto.UserSessionDto; import org.ftclub.cabinet.exception.ExceptionStatus; import org.ftclub.cabinet.exception.ServiceException; import org.ftclub.cabinet.lent.domain.LentHistory; import org.ftclub.cabinet.lent.repository.LentOptionalFetcher; +import org.ftclub.cabinet.mapper.UserMapper; import org.ftclub.cabinet.occupiedtime.OccupiedTimeManager; import org.ftclub.cabinet.user.domain.LentExtension; import org.ftclub.cabinet.user.domain.LentExtensionType; @@ -33,6 +36,7 @@ public class LentExtensionServiceImpl implements LentExtensionService { private final UserOptionalFetcher userOptionalFetcher; private final CabinetProperties cabinetProperties; private final OccupiedTimeManager occupiedTimeManager; + private final UserMapper userMapper; @Override @Scheduled(cron = "${spring.schedule.cron.extension-issue-time}") @@ -67,6 +71,18 @@ public void assignLentExtension(String username) { lentExtensionRepository.save(lentExtension); } + @Override + public List getActiveLentExtensionList( + UserSessionDto userSessionDto) { + log.debug("Called getLentExtensionList {}", userSessionDto.getName()); + return lentExtensionOptionalFetcher.findLentExtensionByUserId(userSessionDto.getUserId()) + .parallelStream() + .filter(lentExtension -> lentExtension.getUsedAt() == null && + lentExtension.getExpiredAt().isAfter(LocalDateTime.now())) + .map(userMapper::toLentExtensionResponseDto) + .collect(Collectors.toList()); + } + @Override @Scheduled(cron = "${spring.schedule.cron.extension-delete-time}") public void deleteLentExtension() { @@ -80,18 +96,19 @@ public void useLentExtension(Long userId, String username) { List findLentExtension = lentExtensionOptionalFetcher.findLentExtensionByUserId(userId) - .stream() - .filter(lentExtension -> - lentExtension.getExpiredAt().isBefore(LocalDateTime.now()) - && lentExtension.getUsedAt() == null) - .collect(Collectors.toList()); + .stream() + .filter(lentExtension -> + lentExtension.getExpiredAt().isAfter(LocalDateTime.now()) + && lentExtension.getUsedAt() == null) + .collect(Collectors.toList()); if (findLentExtension.isEmpty()) { throw new ServiceException(ExceptionStatus.EXTENSION_NOT_FOUND); } LentExtension lentExtension = findLentExtension.get(0); LentHistory lentHistory = lentOptionalFetcher.getActiveLentHistoryWithUserId(userId); lentExtension.use(); - lentHistory.setExpiredAt(lentHistory.getExpiredAt().plusDays(lentExtension.getExtensionPeriod())); + lentHistory.setExpiredAt( + lentHistory.getExpiredAt().plusDays(lentExtension.getExtensionPeriod())); } } diff --git a/backend/src/main/java/org/ftclub/cabinet/user/service/UserFacadeService.java b/backend/src/main/java/org/ftclub/cabinet/user/service/UserFacadeService.java index 67f9c0b9e..55bad8521 100644 --- a/backend/src/main/java/org/ftclub/cabinet/user/service/UserFacadeService.java +++ b/backend/src/main/java/org/ftclub/cabinet/user/service/UserFacadeService.java @@ -17,185 +17,185 @@ public interface UserFacadeService { - /** - * 현재 로그인한 유저의 프로필을 반환합니다. 대여한 사물함 아이디 정보가 포합됩니다. - * - * @param user 로그인한 유저의 정보 - * @return {@link MyProfileResponseDto} 현재 로그인한 유저의 정보 - */ - MyProfileResponseDto getMyProfile(UserSessionDto user); - - /** - * 모든 정지 유저를 반환합니다. - * - * @param page 페이지 번호 - * @param size 페이지 당 길이 - * @param now 현재 시간 - * @return {@link BlockedUserPaginationDto} 모든 정지 유저 - */ - /* 기존 searchByBanUser와 동일한 역할을 합니다. */ - BlockedUserPaginationDto getAllBanUsers(Integer page, Integer size, LocalDateTime now); - - /** - * 유저 이름의 일부를 입력받아 해당하는 유저들의 프로필을 받아옵니다. - * - * @param name 유저 이름의 일부 - * @param page 페이지 번호 - * @param size 페이지 당 길이 - * @return {@link UserProfilePaginationDto} 해당하는 유저들의 프로필 - */ - /*기존 searchByIntraId 메서드와 동일한 역할을 합니다.*/ - UserProfilePaginationDto getUserProfileListByPartialName(String name, Integer page, - Integer size); - - /** - * 유저 이름의 일부를 입력받아 해당 유저들의 캐비넷 정보를 반환합니다. - * - * @param name 유저 이름의 일부 - * @param page 페이지 번호 - * @param size 페이지 당 길이 - * @return {@link UserCabinetPaginationDto} 해당하는 유저들의 캐비넷 정보 - */ - UserCabinetPaginationDto findUserCabinetListByPartialName(String name, Integer page, - Integer size); - - /** - * 모든 유저의 정보를 가져옵니다. - * - * @return 모든 유저의 정보를 가져옵니다. - */ - List getAllUsers(); - - /** - * 유저가 존재하는지 확인합니다. - * - * @param name 유저 이름 - * @return 유저가 존재하면 true, 아니면 false - */ - boolean checkUserExists(String name); - - /** - * 유저를 생성합니다. - * - * @param name 유저 이름 - * @param email 유저 이메일 - * @param blackholedAt 유저 블랙홀 날짜 - * @param role 유저 역할 - */ - void createUser(String name, String email, LocalDateTime blackholedAt, UserRole role); - - /** - * @param clubName 동아리 유저 이름 - */ - void createClubUser(String clubName); - - /** - * 관리자가 존재하는지 확인합니다. - * - * @param email 관리자 이메일 - * @return 관리자가 존재하면 true, 아니면 false - */ - boolean checkAdminUserExists(String email); - - /** - * 관리자를 생성합니다. - * - * @param email 관리자 이메일 - */ - void createAdminUser(String email); - - /** - * 유저를 삭제합니다. - * - * @param userId 유저 고유 아이디 - * @param deletedAt 유저 삭제 날짜 - */ - void deleteUser(Long userId, LocalDateTime deletedAt); - - /** - * 관리자를 삭제합니다. - * - * @param adminUserId 관리자 고유 아이디 - */ - void deleteAdminUser(Long adminUserId); - - /** - * 유저의 권한을 변경합니다. - * - * @param adminUserId 관리자 고유 아이디 - * @param role 관리자 권한 - */ - void updateAdminUserRole(Long adminUserId, AdminRole role); - - /** - * 유저를 어드민으로 승격시킵니다. - * - * @param email 유저 이메일 - */ - void promoteUserToAdmin(String email); - - /** - * 유저의 블랙홀 시간을 변경합니다. - * - * @param userId 유저 고유 아이디 - * @param newBlackholedAt 새로운 유저 블랙홀 시간 - */ - void updateUserBlackholedAt(Long userId, LocalDateTime newBlackholedAt); - - /** - * 유저를 정지시킵니다. - * - * @param userId 유저 고유 아이디 - * @param lentType 현재 대여 타입 - * @param startedAt 대여 시작 날짜 - * @param endedAt 대여 종료 날짜 - * @param expiredAt 대여 만료 날짜 - */ - void banUser(Long userId, LentType lentType, LocalDateTime startedAt, LocalDateTime endedAt, - LocalDateTime expiredAt); - - /** - * 유저의 정지를 해제합니다. - * - * @param userId 유저 고유 아이디 - * @param today 현재 날짜 - */ - void deleteRecentBanHistory(Long userId, LocalDateTime today); - - /** - * 연체 중인 유저 리스트를 반환합니다. - * - * @param page 페이지 번호 - * @param size 페이지 당 길이 - */ - OverdueUserCabinetPaginationDto getOverdueUserList(Integer page, Integer size); - - /** - * 동아리 유저 리스트DTO를 반환합니다. - * - * @param page 페이지 번호 - * @param size 페이지 당 길이 - * @return - */ - ClubUserListDto findAllClubUser(Integer page, Integer size); - - - /** - * 동아리 유저를 삭제합니다. - * - * @param clubId 동아리 고유 아이디 - */ - void deleteClubUser(Long clubId); - - void updateClubUser(Long clubId, String clubName); - - LentExtensionPaginationDto getAllLentExtension(Integer page, Integer size); - - LentExtensionPaginationDto getAllActiveLentExtension(Integer page, Integer size); - - LentExtensionPaginationDto getMyLentExtension(UserSessionDto userSessionDto); - - LentExtensionPaginationDto getMyActiveLentExtension(UserSessionDto userSessionDto); - - void useLentExtension(UserSessionDto userSessionDto); + /** + * 현재 로그인한 유저의 프로필을 반환합니다. 대여한 사물함 아이디 정보가 포합됩니다. + * + * @param user 로그인한 유저의 정보 + * @return {@link MyProfileResponseDto} 현재 로그인한 유저의 정보 + */ + MyProfileResponseDto getMyProfile(UserSessionDto user); + + /** + * 모든 정지 유저를 반환합니다. + * + * @param page 페이지 번호 + * @param size 페이지 당 길이 + * @param now 현재 시간 + * @return {@link BlockedUserPaginationDto} 모든 정지 유저 + */ + /* 기존 searchByBanUser와 동일한 역할을 합니다. */ + BlockedUserPaginationDto getAllBanUsers(Integer page, Integer size, LocalDateTime now); + + /** + * 유저 이름의 일부를 입력받아 해당하는 유저들의 프로필을 받아옵니다. + * + * @param name 유저 이름의 일부 + * @param page 페이지 번호 + * @param size 페이지 당 길이 + * @return {@link UserProfilePaginationDto} 해당하는 유저들의 프로필 + */ + /*기존 searchByIntraId 메서드와 동일한 역할을 합니다.*/ + UserProfilePaginationDto getUserProfileListByPartialName(String name, Integer page, + Integer size); + + /** + * 유저 이름의 일부를 입력받아 해당 유저들의 캐비넷 정보를 반환합니다. + * + * @param name 유저 이름의 일부 + * @param page 페이지 번호 + * @param size 페이지 당 길이 + * @return {@link UserCabinetPaginationDto} 해당하는 유저들의 캐비넷 정보 + */ + UserCabinetPaginationDto findUserCabinetListByPartialName(String name, Integer page, + Integer size); + + /** + * 모든 유저의 정보를 가져옵니다. + * + * @return 모든 유저의 정보를 가져옵니다. + */ + List getAllUsers(); + + /** + * 유저가 존재하는지 확인합니다. + * + * @param name 유저 이름 + * @return 유저가 존재하면 true, 아니면 false + */ + boolean checkUserExists(String name); + + /** + * 유저를 생성합니다. + * + * @param name 유저 이름 + * @param email 유저 이메일 + * @param blackholedAt 유저 블랙홀 날짜 + * @param role 유저 역할 + */ + void createUser(String name, String email, LocalDateTime blackholedAt, UserRole role); + + /** + * @param clubName 동아리 유저 이름 + */ + void createClubUser(String clubName); + + /** + * 관리자가 존재하는지 확인합니다. + * + * @param email 관리자 이메일 + * @return 관리자가 존재하면 true, 아니면 false + */ + boolean checkAdminUserExists(String email); + + /** + * 관리자를 생성합니다. + * + * @param email 관리자 이메일 + */ + void createAdminUser(String email); + + /** + * 유저를 삭제합니다. + * + * @param userId 유저 고유 아이디 + * @param deletedAt 유저 삭제 날짜 + */ + void deleteUser(Long userId, LocalDateTime deletedAt); + + /** + * 관리자를 삭제합니다. + * + * @param adminUserId 관리자 고유 아이디 + */ + void deleteAdminUser(Long adminUserId); + + /** + * 유저의 권한을 변경합니다. + * + * @param adminUserId 관리자 고유 아이디 + * @param role 관리자 권한 + */ + void updateAdminUserRole(Long adminUserId, AdminRole role); + + /** + * 유저를 어드민으로 승격시킵니다. + * + * @param email 유저 이메일 + */ + void promoteUserToAdmin(String email); + + /** + * 유저의 블랙홀 시간을 변경합니다. + * + * @param userId 유저 고유 아이디 + * @param newBlackholedAt 새로운 유저 블랙홀 시간 + */ + void updateUserBlackholedAt(Long userId, LocalDateTime newBlackholedAt); + + /** + * 유저를 정지시킵니다. + * + * @param userId 유저 고유 아이디 + * @param lentType 현재 대여 타입 + * @param startedAt 대여 시작 날짜 + * @param endedAt 대여 종료 날짜 + * @param expiredAt 대여 만료 날짜 + */ + void banUser(Long userId, LentType lentType, LocalDateTime startedAt, LocalDateTime endedAt, + LocalDateTime expiredAt); + + /** + * 유저의 정지를 해제합니다. + * + * @param userId 유저 고유 아이디 + * @param today 현재 날짜 + */ + void deleteRecentBanHistory(Long userId, LocalDateTime today); + + /** + * 연체 중인 유저 리스트를 반환합니다. + * + * @param page 페이지 번호 + * @param size 페이지 당 길이 + */ + OverdueUserCabinetPaginationDto getOverdueUserList(Integer page, Integer size); + + /** + * 동아리 유저 리스트DTO를 반환합니다. + * + * @param page 페이지 번호 + * @param size 페이지 당 길이 + * @return + */ + ClubUserListDto findAllClubUser(Integer page, Integer size); + + + /** + * 동아리 유저를 삭제합니다. + * + * @param clubId 동아리 고유 아이디 + */ + void deleteClubUser(Long clubId); + + void updateClubUser(Long clubId, String clubName); + + LentExtensionPaginationDto getAllLentExtension(Integer page, Integer size); + + LentExtensionPaginationDto getAllActiveLentExtension(Integer page, Integer size); + + LentExtensionPaginationDto getMyLentExtension(UserSessionDto userSessionDto); + + LentExtensionPaginationDto getMyActiveLentExtensionPage(UserSessionDto userSessionDto); + + void useLentExtension(UserSessionDto userSessionDto); } diff --git a/backend/src/main/java/org/ftclub/cabinet/user/service/UserFacadeServiceImpl.java b/backend/src/main/java/org/ftclub/cabinet/user/service/UserFacadeServiceImpl.java index edddbb782..1b5b3d4a6 100644 --- a/backend/src/main/java/org/ftclub/cabinet/user/service/UserFacadeServiceImpl.java +++ b/backend/src/main/java/org/ftclub/cabinet/user/service/UserFacadeServiceImpl.java @@ -57,16 +57,19 @@ public class UserFacadeServiceImpl implements UserFacadeService { @Override public MyProfileResponseDto getMyProfile(UserSessionDto user) { log.debug("Called getMyProfile: {}", user.getName()); + Cabinet cabinet = lentOptionalFetcher.findActiveLentCabinetByUserId(user.getUserId()); BanHistory banHistory = userOptionalFetcher.findRecentActiveBanHistory(user.getUserId(), LocalDateTime.now()); - List lentExtensionNotExpiredByUserId = - lentExtensionOptionalFetcher.findLentExtensionByUserId(user.getUserId()) - .stream().filter(lentExtension -> lentExtension.getUsedAt() == null - && lentExtension.getExpiredAt().isAfter(LocalDateTime.now())) - .collect(Collectors.toList()); - boolean isLentExtensionAvailable = !lentExtensionNotExpiredByUserId.isEmpty(); - return userMapper.toMyProfileResponseDto(user, cabinet, banHistory, isLentExtensionAvailable); + + LentExtensionResponseDto lentExtensionResponseDto = + userMapper.toLentExtensionResponseDto( + lentExtensionOptionalFetcher.findActiveLentExtensionByUserId( + user.getUserId()) + ); + + return userMapper.toMyProfileResponseDto(user, cabinet, banHistory, + lentExtensionResponseDto); } @Override @@ -286,15 +289,10 @@ public LentExtensionPaginationDto getMyLentExtension(UserSessionDto userSessionD } @Override - public LentExtensionPaginationDto getMyActiveLentExtension(UserSessionDto userSessionDto) { + public LentExtensionPaginationDto getMyActiveLentExtensionPage(UserSessionDto userSessionDto) { log.debug("Called getMyActiveLentExtension"); - List result = - lentExtensionOptionalFetcher.findLentExtensionByUserId(userSessionDto.getUserId()) - .parallelStream() - .filter(lentExtension -> lentExtension.getUsedAt() == null && - lentExtension.getExpiredAt().isAfter(LocalDateTime.now())) - .map(userMapper::toLentExtensionResponseDto) - .collect(Collectors.toList()); + List result = lentExtensionService.getActiveLentExtensionList( + userSessionDto); return userMapper.toLentExtensionPaginationDto(result, (long) result.size()); } diff --git a/backend/src/test/java/org/ftclub/cabinet/user/service/UserFacadeServiceTest.java b/backend/src/test/java/org/ftclub/cabinet/user/service/UserFacadeServiceTest.java index ce39e04b7..98bdf641c 100644 --- a/backend/src/test/java/org/ftclub/cabinet/user/service/UserFacadeServiceTest.java +++ b/backend/src/test/java/org/ftclub/cabinet/user/service/UserFacadeServiceTest.java @@ -12,8 +12,10 @@ import org.ftclub.cabinet.mapper.UserMapper; import org.ftclub.cabinet.user.domain.AdminRole; import org.ftclub.cabinet.user.domain.BanHistory; +import org.ftclub.cabinet.user.domain.LentExtension; import org.ftclub.cabinet.user.domain.User; import org.ftclub.cabinet.user.domain.UserRole; +import org.ftclub.cabinet.user.repository.LentExtensionOptionalFetcher; import org.ftclub.cabinet.user.repository.UserOptionalFetcher; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.DisplayName; @@ -76,6 +78,8 @@ public class UserFacadeServiceTest { private UserOptionalFetcher userOptionalFetcher; @Mock private CabinetOptionalFetcher cabinetOptionalFetcher; + @Mock + private LentExtensionOptionalFetcher lentExtensionOptionalFetcher; @Mock(lenient = true) private LentOptionalFetcher lentOptionalFetcher; @@ -98,10 +102,15 @@ public class UserFacadeServiceTest { given(lentOptionalFetcher.findActiveLentCabinetByUserId(1L)).willReturn(cabinet1); given(userOptionalFetcher.findRecentActiveBanHistory(1L, LocalDateTime.now())) .willReturn(null); + given(lentExtensionOptionalFetcher.findLentExtensionByUserId(userSessionDto.getUserId())) + .willReturn(null); + + LentExtension lentExtension = lentExtensionOptionalFetcher.findLentExtensionByUserId( + userSessionDto.getUserId()).get(0); MyProfileResponseDto myProfileResponseDto = new MyProfileResponseDto( userSessionDto.getUserId(), userSessionDto.getName(), - cabinet1.getCabinetId(), null, true); - given(userMapper.toMyProfileResponseDto(userSessionDto, cabinet1, null, true)) + cabinet1.getCabinetId(), null, lentExtension); + given(userMapper.toMyProfileResponseDto(userSessionDto, cabinet1, null, lentExtension)) .willReturn(myProfileResponseDto); // when @@ -126,8 +135,14 @@ public class UserFacadeServiceTest { given(lentOptionalFetcher.findActiveLentCabinetByUserId(2L)).willReturn(null); given(userOptionalFetcher.findRecentActiveBanHistory(eq(2L), any())).willReturn( banHistory1); - given(userMapper.toMyProfileResponseDto(userSessionDto, null, banHistory1, true)).willReturn( - new MyProfileResponseDto(2L, "testUser2", null, testDate.plusDays(1), true)); + given(lentExtensionOptionalFetcher.findLentExtensionByUserId(userSessionDto.getUserId())) + .willReturn(null); + + LentExtension lentExtension = lentExtensionOptionalFetcher.findLentExtensionByUserId( + userSessionDto.getUserId()).get(0); + + given(userMapper.toMyProfileResponseDto(userSessionDto, null, banHistory1, lentExtension)).willReturn( + new MyProfileResponseDto(2L, "testUser2", null, testDate.plusDays(1), lentExtension)); // when MyProfileResponseDto myProfile = userFacadeService.getMyProfile(userSessionDto); diff --git a/config b/config index c1d53791a..a067cf29d 160000 --- a/config +++ b/config @@ -1 +1 @@ -Subproject commit c1d53791a15fcaf68dae0a2ec500dc8b11c07548 +Subproject commit a067cf29d4d5860db60e1ef8ef5141b4e0ab0682 diff --git a/frontend/src/components/CabinetInfoArea/CabinetInfoArea.container.tsx b/frontend/src/components/CabinetInfoArea/CabinetInfoArea.container.tsx index 4434d1b6f..51c933ffe 100644 --- a/frontend/src/components/CabinetInfoArea/CabinetInfoArea.container.tsx +++ b/frontend/src/components/CabinetInfoArea/CabinetInfoArea.container.tsx @@ -331,7 +331,7 @@ const CabinetInfoAreaContainer = (): JSX.Element => { cabinetViewData?.status === "IN_SESSION") && !myCabinetInfo.cabinetId } - isExtensible={myInfo.extensible} + isExtensible={!!myInfo.lentExtensionResponseDto} userModal={userModal} openModal={openModal} closeModal={closeModal} diff --git a/frontend/src/components/Card/Card.tsx b/frontend/src/components/Card/Card.tsx index 0a57c755a..68cdd6c4e 100644 --- a/frontend/src/components/Card/Card.tsx +++ b/frontend/src/components/Card/Card.tsx @@ -104,7 +104,8 @@ export const CardButtonStyled = styled.div<{ cursor: ${(props) => (props.isClickable ? "pointer" : "default")}; margin-left: 10px; &:hover { - text-decoration: ${(props) => (props.isClickable ? "underline" : "none")}; + color: ${(props) => props.isClickable && "var(--black)"}; + font-weight: ${(props) => props.isClickable && 400}; } `; diff --git a/frontend/src/components/Card/CardStyles.ts b/frontend/src/components/Card/CardStyles.ts index f98aaa31a..b355cd7e9 100644 --- a/frontend/src/components/Card/CardStyles.ts +++ b/frontend/src/components/Card/CardStyles.ts @@ -4,7 +4,7 @@ export const CardContentWrapper = styled.div` background-color: var(--white); border-radius: 10px; padding: 15px 0; - margin: 5px 5px 10px 5px; + margin: 5px 5px 5px 5px; width: 90%; display: flex; flex-direction: column; diff --git a/frontend/src/components/Card/ExtensionCard/ExtensionCard.container.tsx b/frontend/src/components/Card/ExtensionCard/ExtensionCard.container.tsx index 4eea4b1dd..640976c33 100644 --- a/frontend/src/components/Card/ExtensionCard/ExtensionCard.container.tsx +++ b/frontend/src/components/Card/ExtensionCard/ExtensionCard.container.tsx @@ -1,14 +1,19 @@ import ExtensionCard from "@/components/Card/ExtensionCard/ExtensionCard"; +import { LentExtensionDto } from "@/types/dto/lent.dto"; -const ExtensionCardContainer = ({ extensible }: { extensible: boolean }) => { +const ExtensionCardContainer = ({ + extensionInfo, +}: { + extensionInfo: LentExtensionDto | null; +}) => { return ( {}, isClickable: false, - isExtensible: extensible, + isExtensible: !!extensionInfo, }} /> ); diff --git a/frontend/src/components/Card/ExtensionCard/ExtensionCard.tsx b/frontend/src/components/Card/ExtensionCard/ExtensionCard.tsx index 592f0c9d6..51e694207 100644 --- a/frontend/src/components/Card/ExtensionCard/ExtensionCard.tsx +++ b/frontend/src/components/Card/ExtensionCard/ExtensionCard.tsx @@ -5,14 +5,15 @@ import { ContentDeatilStyled, ContentInfoStyled, } from "@/components/Card/CardStyles"; -import { getLastDayofMonthString } from "@/utils/dateUtils"; +import { LentExtensionDto } from "@/types/dto/lent.dto"; +import { formatDate } from "@/utils/dateUtils"; interface ExtensionProps { - extensible: boolean; + extensionInfo: LentExtensionDto | null; button: IButtonProps; } -const ExtensionCard = ({ extensible, button }: ExtensionProps) => { +const ExtensionCard = ({ extensionInfo, button }: ExtensionProps) => { return ( { 사용 기한 - {extensible ? getLastDayofMonthString(null, ".") : "-"} + {!!extensionInfo + ? formatDate(new Date(extensionInfo.expiredAt), ".") + : "-"} 연장 기간 - {extensible - ? parseInt(import.meta.env.VITE_EXTENDED_LENT_PERIOD) + "일" - : "-"} + {!!extensionInfo ? extensionInfo.extensionPeriod + "일" : "-"} diff --git a/frontend/src/components/Card/LentInfoCard/LentInfoCard.container.tsx b/frontend/src/components/Card/LentInfoCard/LentInfoCard.container.tsx index aa926e211..59d71afa0 100644 --- a/frontend/src/components/Card/LentInfoCard/LentInfoCard.container.tsx +++ b/frontend/src/components/Card/LentInfoCard/LentInfoCard.container.tsx @@ -86,7 +86,7 @@ const LentInfoCardContainer = ({ name }: { name: string | null }) => { dateUsed, dateLeft, expireDate, - isLented: myCabinetInfo ? true : false, + isLented: myCabinetInfo && myCabinetInfo.lents.length ? true : false, previousUserName: myCabinetInfo?.previousUserName || "", status: myCabinetInfo.status || "", }; diff --git a/frontend/src/components/Card/LentInfoCard/LentInfoCard.tsx b/frontend/src/components/Card/LentInfoCard/LentInfoCard.tsx index 7a1545a10..4d5cfec3c 100644 --- a/frontend/src/components/Card/LentInfoCard/LentInfoCard.tsx +++ b/frontend/src/components/Card/LentInfoCard/LentInfoCard.tsx @@ -115,7 +115,7 @@ const LentInfoCard = ({ const CabinetInfoWrapper = styled.div` display: flex; width: 85%; - margin: 10px 0 15px 0; + margin: 9px 0 9px 0; align-items: center; `; @@ -137,7 +137,12 @@ const CabinetRectangleStyled = styled.div<{ : props.isLented && props.status !== "IN_SESSION" ? "var(--mine)" : "var(--full)"}; - color: ${(props) => (props.banned ? "var(--white)" : "var(--black)")}; + color: ${(props) => + props.banned + ? "var(--white)" + : props.status === "IN_SESSION" + ? "var(--main-color)" + : "var(--black)"}; font-size: 2rem; text-align: center; `; diff --git a/frontend/src/components/Modals/ExtendModal/ExtendModal.tsx b/frontend/src/components/Modals/ExtendModal/ExtendModal.tsx index 06f9cba64..bcb7b11a6 100644 --- a/frontend/src/components/Modals/ExtendModal/ExtendModal.tsx +++ b/frontend/src/components/Modals/ExtendModal/ExtendModal.tsx @@ -18,13 +18,10 @@ import { MyCabinetInfoResponseDto } from "@/types/dto/cabinet.dto"; import IconType from "@/types/enum/icon.type.enum"; import { axiosCabinetById, - axiosExtendLentPeriod, - axiosMyLentInfo, // axiosExtend, // TODO: 연장권 api 생성 후 연결해야 함 + axiosMyLentInfo, + axiosUseExtension, // axiosExtend, // TODO: 연장권 api 생성 후 연결해야 함 } from "@/api/axios/axios.custom"; -import { - getExtendedDateString, - getLastDayofMonthString, -} from "@/utils/dateUtils"; +import { getExtendedDateString } from "@/utils/dateUtils"; const ExtendModal: React.FC<{ onClose: () => void; @@ -42,7 +39,8 @@ const ExtendModal: React.FC<{ isCurrentSectionRenderState ); const formattedExtendedDate = getExtendedDateString( - myLentInfo.lents.length ? myLentInfo.lents[0].expiredAt : undefined + myLentInfo.lents[0].expiredAt, + myInfo.lentExtensionResponseDto?.extensionPeriod ); const extendDetail = `사물함 연장권 사용 시, 대여 기간이 ${formattedExtendedDate} 23:59으로 @@ -50,10 +48,7 @@ const ExtendModal: React.FC<{ 연장권 사용은 취소할 수 없습니다. 연장권을 사용하시겠습니까?`; const extendInfoDetail = `사물함을 대여하시면 연장권 사용이 가능합니다. -연장권은 ${getLastDayofMonthString( - null, - "/" - )} 23:59 이후 만료됩니다.`; +연장권은 ${myInfo.lentExtensionResponseDto?.expiredAt} 23:59 이후 만료됩니다.`; const getModalTitle = (cabinetId: number | null) => { return cabinetId === null ? modalPropsMap[additionalModalType.MODAL_OWN_EXTENSION].title @@ -75,11 +70,11 @@ const ExtendModal: React.FC<{ return; } try { - await axiosExtendLentPeriod(); + await axiosUseExtension(); setMyInfo({ ...myInfo, cabinetId: currentCabinetId, - extensible: false, + lentExtensionResponseDto: null, }); setIsCurrentSectionRender(true); setModalTitle("연장되었습니다"); diff --git a/frontend/src/pages/ProfilePage.tsx b/frontend/src/pages/ProfilePage.tsx index d1b48d68f..caf001527 100644 --- a/frontend/src/pages/ProfilePage.tsx +++ b/frontend/src/pages/ProfilePage.tsx @@ -36,7 +36,9 @@ const ProfilePage = () => { ) : ( - + diff --git a/frontend/src/recoil/atoms.ts b/frontend/src/recoil/atoms.ts index dc1fa709b..2565b9cb1 100644 --- a/frontend/src/recoil/atoms.ts +++ b/frontend/src/recoil/atoms.ts @@ -21,7 +21,7 @@ export const userState = atom({ cabinetId: null, userId: null, name: "default", - extensible: false, + lentExtensionResponseDto: null, }, }); diff --git a/frontend/src/types/dto/lent.dto.ts b/frontend/src/types/dto/lent.dto.ts index efbaba67c..7deea8f7d 100644 --- a/frontend/src/types/dto/lent.dto.ts +++ b/frontend/src/types/dto/lent.dto.ts @@ -66,3 +66,11 @@ export interface CabinetClubStatusRequestDto { cabinetId: number; statusNote: string | null; } + +export interface LentExtensionDto { + lentExtensionId: number; + name: string; + extensionPeriod: number; + expiredAt: Date; + extensionType: string; +} diff --git a/frontend/src/types/dto/user.dto.ts b/frontend/src/types/dto/user.dto.ts index 281dde5b9..01c00166c 100644 --- a/frontend/src/types/dto/user.dto.ts +++ b/frontend/src/types/dto/user.dto.ts @@ -1,4 +1,5 @@ -import { CabinetInfo } from "./cabinet.dto"; +import { CabinetInfo } from "@/types/dto/cabinet.dto"; +import { LentExtensionDto } from "@/types/dto/lent.dto"; export interface UserDto { userId: number | null; // 42 고유 ID @@ -6,7 +7,7 @@ export interface UserDto { // TODO: // mock 데이터와 충돌 생겨서 옵셔널 필드로 바꿨습니다. 추후 수정 필요합니다. cabinetId: number | null; // 캐비닛 고유 ID - extensible: boolean; + lentExtensionResponseDto: LentExtensionDto | null; } export interface UserInfo { diff --git a/frontend/src/utils/dateUtils.ts b/frontend/src/utils/dateUtils.ts index bc832a54e..865ed2459 100644 --- a/frontend/src/utils/dateUtils.ts +++ b/frontend/src/utils/dateUtils.ts @@ -43,20 +43,16 @@ export const getShortenedExpireDateString = ( return formatDate(new Date(newExpireDate), "/"); }; -export const getExtendedDateString = (existExpireDate?: Date) => { - let expireDate = existExpireDate ? new Date(existExpireDate) : new Date(); - expireDate.setDate( - expireDate.getDate() + parseInt(import.meta.env.VITE_EXTENDED_LENT_PERIOD) - ); +export const getExtendedDateString = ( + existExpireDate: Date | undefined, + dateToExtend: number | undefined +) => { + if (existExpireDate === undefined || dateToExtend === undefined) return; + let expireDate = new Date(existExpireDate); + expireDate.setDate(expireDate.getDate() + dateToExtend); return formatDate(expireDate, "/"); }; -export const getLastDayofMonthString = (date: Date | null, divider: string) => { - if (date === null) date = new Date(); - let lastDay = new Date(date.getFullYear(), date.getMonth() + 1, 0); - return formatDate(lastDay, divider); -}; - export const getTotalPage = (totalLength: number, size: number) => { return Math.ceil(totalLength / size); };