Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package plango.admin.application.dto.response;

import java.time.LocalDate;

public record AdminDashboardDailyCountResponse(
LocalDate date,
long newMemberCount
) {}

Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package plango.admin.application.dto.response;

import lombok.Builder;

public record AdminDashboardStatsResponse(
long totalMemberCount,
long todayNewMemberCount,
long totalRoomCount,
long todayNewRoomCount,
long totalScheduleCount,
long todayNewScheduleCount,
long totalNoticeCount,
long totalInconvenienceReportCount
) {

@Builder
public AdminDashboardStatsResponse {
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package plango.admin.application.dto.response;

public record AdminMonitoringStatsResponse(
long totalMemberCount,
long totalRoomCount,
long totalTripCount,
long totalFriendRequestCount,
long totalReportCount,
long waitingReportCount,
long processingReportCount,
long completedReportCount,
long totalNoticeCount
) {}

Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package plango.admin.application.usecase;

import java.time.LocalDate;
import java.time.LocalDateTime;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import plango.admin.application.dto.response.AdminDashboardStatsResponse;
import plango.member.domain.repository.MemberRepository;
import plango.notice.domain.repository.NoticeRepository;
import plango.report.domain.repository.InconvenienceReportRepository;
import plango.room.domain.repository.RoomRepository;
import plango.room.domain.repository.RoomScheduleRepository;

@Service
@RequiredArgsConstructor
@Transactional(readOnly = true)
public class AdminDashboardStatsUseCase {

private final MemberRepository memberRepository;
private final RoomRepository roomRepository;
private final RoomScheduleRepository roomScheduleRepository;
private final NoticeRepository noticeRepository;
private final InconvenienceReportRepository inconvenienceReportRepository;

public AdminDashboardStatsResponse execute() {
LocalDate today = LocalDate.now();

LocalDateTime startOfToday = today.atStartOfDay();
LocalDateTime endOfToday = today.plusDays(1)
.atStartOfDay();

long totalMemberCount = memberRepository.count();
long todayNewMemberCount =
memberRepository.countByCreatedAtBetween(startOfToday, endOfToday);

long totalRoomCount = roomRepository.count();
long todayNewRoomCount =
roomRepository.countByCreatedAtBetween(startOfToday, endOfToday);

long totalScheduleCount = roomScheduleRepository.count();
long todayNewScheduleCount =
roomScheduleRepository.countByCreatedAtBetween(startOfToday, endOfToday);

long totalNoticeCount = noticeRepository.count();

long totalInconvenienceReportCount = inconvenienceReportRepository.count();

return AdminDashboardStatsResponse.builder()
.totalMemberCount(totalMemberCount)
.todayNewMemberCount(todayNewMemberCount)
.totalRoomCount(totalRoomCount)
.todayNewRoomCount(todayNewRoomCount)
.totalScheduleCount(totalScheduleCount)
.todayNewScheduleCount(todayNewScheduleCount)
.totalNoticeCount(totalNoticeCount)
.totalInconvenienceReportCount(totalInconvenienceReportCount)
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package plango.admin.presentation;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import plango.admin.application.dto.response.AdminDashboardStatsResponse;
import plango.admin.application.usecase.AdminDashboardStatsUseCase;
import plango.global.common.response.CommonResponse;
import plango.global.common.response.ResponseMessage;

@Tag(
name = "관리자 대시보드",
description = "관리자 모니터링용 통계 API"
)
@RestController
@RequiredArgsConstructor
@RequestMapping("/api/admin/dashboard")
public class AdminDashboardController {

private final AdminDashboardStatsUseCase adminDashboardStatsUseCase;

@Operation(
summary = "대시보드 통계 조회",
description = "회원 수, 여행방 수, 일정 수, 공지사항 수, 신고 건수 등을 통합 조회합니다."
)
@GetMapping
public CommonResponse<AdminDashboardStatsResponse> getStats() {
AdminDashboardStatsResponse response = adminDashboardStatsUseCase.execute();

return CommonResponse.success(
ResponseMessage.ADMIN_DASHBOARD_STATS_SUCCESS,
response
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ public enum ResponseMessage {
ADMIN_REPORT_LIST_GET_SUCCESS(0,"관리자 신고 목록 조회 성공"),
ADMIN_REPORT_DETAIL_GET_SUCCESS(0,"관리자 신고 상세 조회 성공"),
ADMIN_REPORT_STATUS_UPDATE_SUCCESS(0,"관리자 신고 상태 변경 성공"),
ADMIN_DASHBOARD_STATS_SUCCESS(0,"관리자 대시보드 통계 조회 성공"),

//===== 공지사항 =====
NOTICE_CREATE_SUCCESS(0,"공지사항 생성 성공"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@ List<Member> findByLoginIdContainingOrEmailContainingOrNicknameContaining(
String nickname
);


long count();

long countByCreatedAtBetween(java.time.LocalDateTime start, java.time.LocalDateTime end);

boolean existsByLoginId(String loginId);

boolean existsByEmail(String email);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,8 @@
import java.util.List;

public interface NoticeRepository extends JpaRepository<Notice, Long> {

List<Notice> findAllByOrderByIdDesc();

List<Notice> findTop5ByOrderByCreatedAtDesc();
}
17 changes: 17 additions & 0 deletions src/main/java/plango/room/domain/repository/RoomRepository.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,27 @@
import plango.room.domain.entity.Room;

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

public interface RoomRepository extends JpaRepository<Room, Long> {

// 전체 여행방 개수 조회
long count();

// 특정 기간 동안 생성된 여행방 수 조회
@Query("""
select count(r)
from Room r
where r.createdAt between :start and :end
""")
long countCreatedAtBetween(
@Param("start") LocalDate start,
@Param("end") LocalDate end
);

long countByCreatedAtBetween(LocalDateTime start, LocalDateTime end);

// 특정 시작일 기준으로 여행방 조회 (기존 메서드 유지)
List<Room> findByStartDate(LocalDate startDate);

Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
package plango.room.domain.repository;

import java.util.List;
import java.time.LocalDateTime;
import org.springframework.data.jpa.repository.JpaRepository;
import plango.room.domain.entity.RoomSchedule;

public interface RoomScheduleRepository extends JpaRepository<RoomSchedule, Long> {

List<RoomSchedule> findAllByRoomIdAndDayIndexOrderByStartTimeAsc(Long roomId, int dayIndex);

long countByCreatedAtBetween(LocalDateTime start, LocalDateTime end);
}