Skip to content

Commit

Permalink
Merge pull request #160 from 4bujak-4bujak/feature/schedule
Browse files Browse the repository at this point in the history
feat: 예약 가능 공간 개수, 이번주 일정 기능 구현
  • Loading branch information
zoomin3022 authored Jun 10, 2024
2 parents 6548fcc + 94b99a5 commit 818a556
Show file tree
Hide file tree
Showing 8 changed files with 134 additions and 23 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.example.sabujak.branch.controller;

import com.example.sabujak.branch.dto.response.AvailableSpaceCountDto;
import com.example.sabujak.branch.dto.response.BranchDistanceResponseDto;
import com.example.sabujak.branch.dto.response.BranchResponseDto;
import com.example.sabujak.branch.dto.response.BranchWithSpaceDto;
Expand Down Expand Up @@ -67,9 +68,21 @@ public ResponseEntity<Response<BranchWithSpaceDto>> getBranchWithSpace(@PathVari
@GetMapping("/{branchId}/near")
public ResponseEntity<Response<List<BranchDistanceResponseDto>>> getNearBranchesByCurrentBranch(
@PathVariable(name = "branchId") Long branchId
){
) {
return ResponseEntity.ok(Response.success(branchService.getNearBranchesByCurrentBranch(branchId)));
}


@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "조회 성공", content = @Content(schema = @Schema(implementation = Response.class))),
@ApiResponse(responseCode = "404", description = "조회 실패", content = @Content(schema = @Schema(implementation = Response.class)))})
@Operation(summary = "지점 예약 가능한 공간", description = "지점의 Id를 받아 총, 사용 가능한 회의실 리차징 포커스 개수 반환")
@Parameters({
@Parameter(name = "branchId", description = "지점 Id", example = "1")
})
@GetMapping("/{branchId}/available-count")
public ResponseEntity<Response<AvailableSpaceCountDto>> getAvailableSpaceCount(@PathVariable Long branchId) {
return ResponseEntity.ok(Response.success(branchService.getAvailableSpaceCount(branchId)));
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.example.sabujak.branch.dto.response;

public record AvailableSpaceCountDto(
int totalMeetingRoomCount,
int availableMeetingRoomCount,
int totalRechargingRoomCount,
int availableRechargingRoomCount,
int totalFocusDeskCount,
int availableFocusDeskCount) {
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
package com.example.sabujak.branch.service;

import com.example.sabujak.branch.dto.response.AvailableSpaceCountDto;
import com.example.sabujak.branch.dto.response.BranchDistanceResponseDto;
import com.example.sabujak.branch.dto.response.BranchResponseDto;
import com.example.sabujak.branch.dto.response.BranchWithSpaceDto;
import com.example.sabujak.branch.entity.Branch;
import com.example.sabujak.branch.exception.BranchErrorCode;
import com.example.sabujak.branch.exception.BranchException;
import com.example.sabujak.branch.repository.BranchRepository;
import com.example.sabujak.space.repository.SpaceRepository;
import com.example.sabujak.space.repository.meetingroom.MeetingRoomRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
Expand All @@ -16,6 +19,7 @@
import java.time.format.DateTimeFormatter;
import java.util.List;

import static com.example.sabujak.branch.exception.BranchErrorCode.BRANCH_NOT_FOUND;
import static com.example.sabujak.branch.exception.BranchErrorCode.ENTITY_NOT_FOUND_BY_NAME;
import static java.util.function.Predicate.not;

Expand All @@ -28,6 +32,7 @@ public class BranchService {
private static final int MAX_SEARCH_COUNT = 2;
private final BranchRepository branchRepository;
private final MeetingRoomRepository meetingRoomRepository;
private final SpaceRepository spaceRepository;

public BranchResponseDto findByBranchName(String branchName) {
log.info("[BranchService findByBranchName] branchName: {}", branchName);
Expand All @@ -48,7 +53,7 @@ public BranchWithSpaceDto getBranchWithSpace(LocalDateTime now, String branchNam
int branchTotalMeetingRoomCount = meetingRoomRepository.countTotalMeetingRoom(branchName);
int branchActiveMeetingRoomCount = meetingRoomRepository.countActiveMeetingRoom(now, branchName);

return new BranchWithSpaceDto(branch.getBranchId(), branch.getBranchName(),branch.getBranchAddress(),branchTotalMeetingRoomCount,branchActiveMeetingRoomCount);
return new BranchWithSpaceDto(branch.getBranchId(), branch.getBranchName(), branch.getBranchAddress(), branchTotalMeetingRoomCount, branchActiveMeetingRoomCount);
}

public List<BranchDistanceResponseDto> getNearBranchesByCurrentBranch(Long branchId) {
Expand Down Expand Up @@ -91,8 +96,22 @@ private double calculateDistance(double lat1, double lon1, double lat2, double l
}


public AvailableSpaceCountDto getAvailableSpaceCount(Long branchId) {
LocalDateTime now = LocalDateTime.now();
Branch branch = branchRepository.findById(branchId)
.orElseThrow(() -> new BranchException(BRANCH_NOT_FOUND));

List<Long> allCounts = spaceRepository.countAllSpaceByBranch(branch);
Long focusDeskTotalCount = allCounts.get(0);
Long meetingRoomTotalCount = allCounts.get(1);
Long rechargingRoomTotalCount = allCounts.get(2);

Long focusDeskUsingCount = spaceRepository.countUsingSpaceByBranchAndDtype(branch, now, "FocusDesk");
Long meetingRoomUsingCount = spaceRepository.countUsingSpaceByBranchAndDtype(branch, now, "MeetingRoom");
Long rechargingRoomUsingCount = spaceRepository.countUsingSpaceByBranchAndDtype(branch, now, "RechargingRoom");


return new AvailableSpaceCountDto(Math.toIntExact(meetingRoomTotalCount), Math.toIntExact(meetingRoomTotalCount - meetingRoomUsingCount),
Math.toIntExact(rechargingRoomTotalCount), Math.toIntExact(rechargingRoomTotalCount - rechargingRoomUsingCount),
Math.toIntExact(focusDeskTotalCount), Math.toIntExact(focusDeskTotalCount - focusDeskUsingCount));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.web.bind.annotation.*;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;

Expand Down Expand Up @@ -65,13 +66,15 @@ public ResponseEntity<Response<List<ReservationHistoryResponse.ReservationForLis
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "조회 성공", content = @Content(schema = @Schema(implementation = Response.class))),
@ApiResponse(responseCode = "404", description = "조회 실패", content = @Content(schema = @Schema(implementation = Response.class)))})
@Operation(summary = "당일 예약 총 수", description = "오늘 n개의 예약 기능 에서 n 반환")
@Operation(summary = "이번 주 일정 조회", description = "이번주 내에 있는 예약 중 하루 날짜를 받으면 해당 날짜 일정 보여줌 (일단 이번주인지 검증은 안함)")
@Parameters({
@Parameter(name = "access", hidden = true)
@Parameter(name = "access", hidden = true),
@Parameter(name = "localDate", description = "날짜", example = "2024-06-10", required = true)
})
@GetMapping("/today/count")
public ResponseEntity<Response<ReservationHistoryResponse.TodayReservationCount>> getTodayReservationCount(@AuthenticationPrincipal AuthRequestDto.Access access) {
return ResponseEntity.ok(Response.success(reservationService.getTodayReservationCount(access.getEmail())));
@GetMapping("/week")
public ResponseEntity<Response<List<ReservationHistoryResponse.ReservationForList>>> getWeekReservations(@AuthenticationPrincipal AuthRequestDto.Access access,
@RequestParam LocalDate localDate) {
return ResponseEntity.ok(Response.success(reservationService.getReservationsOfDay(access.getEmail(), localDate)));
}

@ApiResponses(value = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,6 @@

public class ReservationHistoryResponse {

public record TodayReservationCount(Integer count) {
}

@Getter
public static class ReservationForList {
private Long reservationId;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;
Expand Down Expand Up @@ -253,33 +254,55 @@ public ReservationResponseDto.CheckFocusDeskOverlap checkFocusDeskOverlap(String
return new ReservationResponseDto.CheckFocusDeskOverlap(false);
}

public ReservationHistoryResponse.TodayReservationCount getTodayReservationCount(String email) {
public List<ReservationHistoryResponse.ReservationForList> getTodayReservations(String email) {
List<ReservationHistoryResponse.ReservationForList> reservationForLists = new ArrayList<>();

LocalDateTime now = LocalDateTime.now();

final Member member = memberRepository.findByMemberEmail(email)
.orElseThrow(() -> new AuthException(ACCOUNT_NOT_EXISTS));

Integer todayReservationCount = reservationRepository.countTodayReservation(member, now);
List<Reservation> todayReservations = reservationRepository.findReservationsToday(member, now);
List<MemberReservation> memberReservations = memberReservationRepository.findMemberReservationsByReservations(todayReservations);

Map<Reservation, List<MemberReservation>> memberReservationMap = memberReservations.stream()
.collect(Collectors.groupingBy(MemberReservation::getReservation));

for (Reservation reservation : todayReservations) {
List<MemberReservation> memberReservationsInReservation = memberReservationMap.get(reservation);

Optional<MemberReservationType> memberType = memberReservationsInReservation.stream()
.filter(memberReservation -> memberReservation.getMember().getMemberId().equals(member.getMemberId()))
.map(MemberReservation::getMemberReservationType)
.findFirst();

reservationForLists.add(ReservationHistoryResponse.ReservationForList.of(
reservation,
reservation.getSpace(),
memberReservationsInReservation.stream()
.map(MemberReservation::getMember)
.collect(Collectors.toList()),
memberType.orElse(null)));
}

return new ReservationHistoryResponse.TodayReservationCount(todayReservationCount);
return reservationForLists;
}

public List<ReservationHistoryResponse.ReservationForList> getTodayReservations(String email) {
public List<ReservationHistoryResponse.ReservationForList> getReservationsOfDay(String email, LocalDate localDate) {
List<ReservationHistoryResponse.ReservationForList> reservationForLists = new ArrayList<>();

LocalDateTime now = LocalDateTime.now();
LocalDateTime targetDay = localDate.atStartOfDay();

final Member member = memberRepository.findByMemberEmail(email)
.orElseThrow(() -> new AuthException(ACCOUNT_NOT_EXISTS));

List<Reservation> todayReservations = reservationRepository.findReservationsToday(member, now);
List<MemberReservation> memberReservations = memberReservationRepository.findMemberReservationsByReservations(todayReservations);
List<Reservation> reservations = reservationRepository.findReservationsWithDuration(member, targetDay, 0, 0);
List<MemberReservation> memberReservations = memberReservationRepository.findMemberReservationsByReservations(reservations);

Map<Reservation, List<MemberReservation>> memberReservationMap = memberReservations.stream()
.collect(Collectors.groupingBy(MemberReservation::getReservation));

for (Reservation reservation : todayReservations) {
for (Reservation reservation : reservations) {
List<MemberReservation> memberReservationsInReservation = memberReservationMap.get(reservation);

Optional<MemberReservationType> memberType = memberReservationsInReservation.stream()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
package com.example.sabujak.space.repository;

import com.example.sabujak.space.entity.MeetingRoomType;
import com.example.sabujak.branch.entity.Branch;

import java.time.LocalDateTime;
import java.util.List;

public interface SpaceRepositoryCustom {
Integer countAllRechargingRoomByBranch(Long branchId);

List<Long> countAllSpaceByBranch(Branch branch);
Long countUsingSpaceByBranchAndDtype(Branch branch, LocalDateTime now, String dtype);
}
Original file line number Diff line number Diff line change
@@ -1,16 +1,22 @@
package com.example.sabujak.space.repository;

import com.example.sabujak.branch.entity.Branch;
import com.example.sabujak.branch.entity.QBranch;
import com.example.sabujak.space.entity.MeetingRoomType;
import com.example.sabujak.space.entity.QSpace;
import com.example.sabujak.reservation.entity.ReservationStatus;
import com.querydsl.core.types.dsl.BooleanExpression;
import com.querydsl.jpa.impl.JPAQueryFactory;
import lombok.RequiredArgsConstructor;

import java.time.LocalDateTime;
import java.util.List;

import static com.example.sabujak.branch.entity.QBranch.branch;
import static com.example.sabujak.reservation.entity.QMemberReservation.memberReservation;
import static com.example.sabujak.reservation.entity.QReservation.reservation;
import static com.example.sabujak.space.entity.QSpace.space;

@RequiredArgsConstructor
public class SpaceRepositoryImpl implements SpaceRepositoryCustom{
public class SpaceRepositoryImpl implements SpaceRepositoryCustom {
private final JPAQueryFactory queryFactory;

@Override
Expand All @@ -24,4 +30,38 @@ public Integer countAllRechargingRoomByBranch(Long branchId) {
)
.fetchFirst());
}

@Override
public List<Long> countAllSpaceByBranch(Branch branch) {
return queryFactory.select(space.count())
.from(space)
.join(space.branch, QBranch.branch)
.where(
space.branch.eq(branch)
)
.groupBy(space.dtype)
.orderBy(space.dtype.asc())
.fetch();
}

@Override
public Long countUsingSpaceByBranchAndDtype(Branch branch, LocalDateTime now, String dtype) {
return queryFactory.select(space.count())
.from(space)
.join(space.branch, QBranch.branch)
.join(space.reservations, reservation)
.join(reservation.memberReservations, memberReservation)
.where(
space.branch.eq(branch),
nowUsing(now),
memberReservation.memberReservationStatus.eq(ReservationStatus.ACCEPTED),
space.dtype.eq(dtype)
)
.fetchFirst();
}

private BooleanExpression nowUsing(LocalDateTime now) {
return reservation.reservationStartDateTime.before(now.plusSeconds(1))
.and(reservation.reservationEndDateTime.after(now));
}
}

0 comments on commit 818a556

Please sign in to comment.