diff --git a/nowait-app-admin-api/src/main/java/com/nowait/applicationadmin/reservation/dto/WaitingUserResponse.java b/nowait-app-admin-api/src/main/java/com/nowait/applicationadmin/reservation/dto/WaitingUserResponse.java index 95fbf33a..23d5fa89 100644 --- a/nowait-app-admin-api/src/main/java/com/nowait/applicationadmin/reservation/dto/WaitingUserResponse.java +++ b/nowait-app-admin-api/src/main/java/com/nowait/applicationadmin/reservation/dto/WaitingUserResponse.java @@ -9,7 +9,6 @@ import lombok.Builder; import lombok.Getter; - @Getter @AllArgsConstructor @Builder @@ -31,6 +30,9 @@ public class WaitingUserResponse { @Schema(description = "대기 등록 시각", example = "2025-07-22T16:00:00") private LocalDateTime createdAt; + @Schema(description = "호출 시각", example = "2025-07-22T16:10:00") + private LocalDateTime calledAt; + @Schema(description = "대기 상태", example = "CALLING") private String status; @@ -48,13 +50,15 @@ public static WaitingUserResponse fromEntity(Reservation reservation) { .build(); } - public static WaitingUserResponse fromRedis(String reservationId, String userId, Integer partySize, String userName, LocalDateTime createdAt, String status, Double score) { + public static WaitingUserResponse fromRedis(String reservationId, String userId, Integer partySize, String userName, + LocalDateTime createdAt, LocalDateTime calledAt, String status, Double score) { return WaitingUserResponse.builder() .reservationNumber(reservationId) .userId(userId) .partySize(partySize) .userName(userName) .createdAt(createdAt) + .calledAt(calledAt) .status(status) .score(score) .build(); diff --git a/nowait-app-admin-api/src/main/java/com/nowait/applicationadmin/reservation/service/ReservationService.java b/nowait-app-admin-api/src/main/java/com/nowait/applicationadmin/reservation/service/ReservationService.java index 3ed9fa8d..de1e0474 100644 --- a/nowait-app-admin-api/src/main/java/com/nowait/applicationadmin/reservation/service/ReservationService.java +++ b/nowait-app-admin-api/src/main/java/com/nowait/applicationadmin/reservation/service/ReservationService.java @@ -134,6 +134,7 @@ public List getAllWaitingUserDetails(Long storeId) { String pk = RedisKeyUtils.buildWaitingPartySizeKeyPrefix() + storeId; String sk = RedisKeyUtils.buildWaitingStatusKeyPrefix() + storeId; String nk = RedisKeyUtils.buildReservationNumberKey(storeId); + String cak = RedisKeyUtils.buildWaitingCalledAtKeyPrefix() + storeId; String qk = RedisKeyUtils.buildWaitingKeyPrefix() + storeId; List pipeline = redisTemplate.executePipelined((RedisCallback)conn -> { @@ -143,6 +144,7 @@ public List getAllWaitingUserDetails(Long storeId) { conn.hGet(pk.getBytes(), uid); // partySize conn.hGet(sk.getBytes(), uid); // status conn.hGet(nk.getBytes(), uid); // reservationId + conn.hGet(cak.getBytes(), uid); // calledAt conn.zScore(qk.getBytes(), uid); // score (등록 시각) } return null; @@ -158,6 +160,7 @@ public List getAllWaitingUserDetails(Long storeId) { Integer partySize = Optional.ofNullable((String)it.next()).map(Integer::valueOf).orElse(0); String status = (String)it.next(); String reservationId = (String)it.next(); + String calledAtStr = (String)it.next(); Double score = (Double)it.next(); // score → createdAt @@ -165,10 +168,15 @@ public List getAllWaitingUserDetails(Long storeId) { ? Instant.ofEpochMilli(score.longValue()).atZone(zone).toLocalDateTime() : null; + LocalDateTime calledAt = calledAtStr != null + ? Instant.ofEpochMilli(Long.parseLong(calledAtStr)).atZone(zone).toLocalDateTime() + : null; + String userName = nicknameMap.getOrDefault(userId, "Unknown"); result.add( - WaitingUserResponse.fromRedis(reservationId, userId, partySize, userName, createdAt, status, score)); + WaitingUserResponse.fromRedis(reservationId, userId, partySize, userName, createdAt, calledAt, status, + score)); } return result; @@ -220,7 +228,8 @@ private Reservation findTodayReservation(Long storeId, String userId) { * - CANCELLED : Redis에서 삭제 → DB 저장 → 취소 메시지 반환 */ @Transactional - public EntryStatusResponseDto processEntryStatus(Long storeId, String userId, MemberDetails member, ReservationStatus newStatus) { + public EntryStatusResponseDto processEntryStatus(Long storeId, String userId, MemberDetails member, + ReservationStatus newStatus) { authorize(storeId, member); @@ -235,7 +244,7 @@ public EntryStatusResponseDto processEntryStatus(Long storeId, String userId, Me LocalDateTime requestedAt = score != null ? Instant.ofEpochMilli(score.longValue()).atZone(ZoneId.of("Asia/Seoul")).toLocalDateTime() : LocalDateTime.now(); - LocalDateTime now = LocalDateTime.now(); + LocalDateTime now = LocalDateTime.now(ZoneId.of("Asia/Seoul")); switch (newStatus) { case CALLING: @@ -243,8 +252,8 @@ public EntryStatusResponseDto processEntryStatus(Long storeId, String userId, Me throw new IllegalStateException("WAITING 상태에서만 CALLING 가능합니다."); } waitingRedisRepository.setWaitingStatus(storeId, userId, ReservationStatus.CALLING.name()); - waitingRedisRepository.setWaitingCalledAt(storeId, userId, now.atZone(ZoneId.of("Asia/Seoul")).toInstant().toEpochMilli()); - + waitingRedisRepository.setWaitingCalledAt(storeId, userId, + now.atZone(ZoneId.of("Asia/Seoul")).toInstant().toEpochMilli()); return EntryStatusResponseDto.builder() .reservationNumber(reservationNumber) @@ -259,7 +268,8 @@ public EntryStatusResponseDto processEntryStatus(Long storeId, String userId, Me case CONFIRMED: // 1) 기존 대기 중이거나 호출 중일 때: Redis → DB 최초 저장 - if (ReservationStatus.WAITING.name().equals(currStatus) || ReservationStatus.CALLING.name().equals(currStatus)) { + if (ReservationStatus.WAITING.name().equals(currStatus) || ReservationStatus.CALLING.name() + .equals(currStatus)) { // Redis 전부 삭제 waitingRedisRepository.deleteWaiting(storeId, userId);