diff --git a/build.gradle b/build.gradle index 1139ff13..3d21d352 100644 --- a/build.gradle +++ b/build.gradle @@ -1,6 +1,6 @@ plugins { id 'java' - id 'org.springframework.boot' version '3.4.5' + id 'org.springframework.boot' version '3.4.6' id 'io.spring.dependency-management' version '1.1.6' } @@ -50,19 +50,19 @@ dependencies { implementation 'com.github.ben-manes.caffeine:caffeine' developmentOnly 'org.springframework.boot:spring-boot-devtools' developmentOnly 'org.springframework.boot:spring-boot-docker-compose' - runtimeOnly 'org.postgresql:postgresql:42.7.4' + runtimeOnly 'org.postgresql:postgresql:42.7.5' annotationProcessor 'org.springframework.boot:spring-boot-configuration-processor' testImplementation 'org.springframework.boot:spring-boot-starter-test' testImplementation 'org.springframework.security:spring-security-test' testRuntimeOnly 'org.junit.platform:junit-platform-launcher' //JWT - implementation 'io.jsonwebtoken:jjwt-api:0.12.6' // JWT API - runtimeOnly 'io.jsonwebtoken:jjwt-impl:0.12.6' // JWT 구현체 - runtimeOnly 'io.jsonwebtoken:jjwt-jackson:0.12.6' // JSON 처리를 위한 Jackson 모듈 + implementation 'io.jsonwebtoken:jjwt-api:0.12.7' // JWT API + runtimeOnly 'io.jsonwebtoken:jjwt-impl:0.12.7' // JWT 구현체 + runtimeOnly 'io.jsonwebtoken:jjwt-jackson:0.12.7' // JSON 처리를 위한 Jackson 모듈 implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310' - compileOnly 'jakarta.servlet:jakarta.servlet-api:6.1.0' // JWT 인증 관련 jakarta 추가 + compileOnly 'jakarta.servlet:jakarta.servlet-api:6.0.0' // JWT 인증 관련 jakarta 추가 //Swagger - implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.8.6' + implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.8.7' //ULID implementation 'de.huxhorn.sulky:de.huxhorn.sulky.ulid:8.3.0' implementation 'org.springframework.boot:spring-boot-starter-oauth2-resource-server' @@ -78,10 +78,10 @@ dependencies { implementation 'net.bramp.ffmpeg:ffmpeg:0.6.2' //Keycloak - implementation 'org.keycloak:keycloak-admin-client:26.0.5' + implementation 'org.keycloak:keycloak-admin-client:26.0.6' //FixtureMonkey - testImplementation("com.navercorp.fixturemonkey:fixture-monkey-starter:1.1.10") + testImplementation("com.navercorp.fixturemonkey:fixture-monkey-starter:1.1.11") } tasks.named('test') { useJUnitPlatform() diff --git a/src/main/java/com/springboot/api/counselsession/dto/counselsession/CounselSessionStatRes.java b/src/main/java/com/springboot/api/counselsession/dto/counselsession/CounselSessionStatRes.java index b58d1310..338b8acb 100644 --- a/src/main/java/com/springboot/api/counselsession/dto/counselsession/CounselSessionStatRes.java +++ b/src/main/java/com/springboot/api/counselsession/dto/counselsession/CounselSessionStatRes.java @@ -2,8 +2,8 @@ import lombok.Builder; -public record CounselSessionStatRes(long totalSessionCount, long counseleeCountForThisMonth, - long totalCaringMessageCount, long counselHoursForThisMonth) { +public record CounselSessionStatRes(long counselHoursThisMonth, long counseleeCountForThisMonth, + long medicationCounselCountThisYear, long counselorCountThisYear) { @Builder public CounselSessionStatRes { diff --git a/src/main/java/com/springboot/api/counselsession/repository/CounselSessionRepositoryCustom.java b/src/main/java/com/springboot/api/counselsession/repository/CounselSessionRepositoryCustom.java index 57cf5890..39604a84 100644 --- a/src/main/java/com/springboot/api/counselsession/repository/CounselSessionRepositoryCustom.java +++ b/src/main/java/com/springboot/api/counselsession/repository/CounselSessionRepositoryCustom.java @@ -38,4 +38,6 @@ PageRes findByCounseleeNameAndCounselorNameAndScheduledDateTimeA List findValidCounselSessionsByCounseleeId(String counseleeId); void bulkUpdateCounselSessionNum(Map sessionUpdates); + + Long countDistinctCounselorsByCompletedSessionsInYear(int year); } diff --git a/src/main/java/com/springboot/api/counselsession/repository/CounselSessionRepositoryImpl.java b/src/main/java/com/springboot/api/counselsession/repository/CounselSessionRepositoryImpl.java index 9464789f..cd781b92 100644 --- a/src/main/java/com/springboot/api/counselsession/repository/CounselSessionRepositoryImpl.java +++ b/src/main/java/com/springboot/api/counselsession/repository/CounselSessionRepositoryImpl.java @@ -267,4 +267,17 @@ public void bulkUpdateCounselSessionNum(Map sessionUpdates) { .where(counselSession.id.in(sessionUpdates.keySet())) .execute(); } + + @Override + public Long countDistinctCounselorsByCompletedSessionsInYear(int year) { + return queryFactory + .select(counselSession.counselor.countDistinct()) + .from(counselSession) + .where( + counselSession.status.eq(ScheduleStatus.COMPLETED), + counselSession.startDateTime.year().eq(year), + counselSession.counselor.isNotNull(), + counselSession.counselor.status.eq(CounselorStatus.ACTIVE)) + .fetchOne(); + } } \ No newline at end of file diff --git a/src/main/java/com/springboot/api/counselsession/repository/MedicationCounselRepository.java b/src/main/java/com/springboot/api/counselsession/repository/MedicationCounselRepository.java index 62821787..dc79ae8c 100644 --- a/src/main/java/com/springboot/api/counselsession/repository/MedicationCounselRepository.java +++ b/src/main/java/com/springboot/api/counselsession/repository/MedicationCounselRepository.java @@ -1,5 +1,6 @@ package com.springboot.api.counselsession.repository; +import java.time.LocalDateTime; import java.util.Optional; import org.springframework.data.jpa.repository.JpaRepository; @@ -9,4 +10,6 @@ public interface MedicationCounselRepository extends JpaRepository { Optional findByCounselSessionId(String counselSessionId); + + long countByCreatedDatetimeBetween(LocalDateTime startDate, LocalDateTime endDate); } diff --git a/src/main/java/com/springboot/api/counselsession/service/CounselSessionService.java b/src/main/java/com/springboot/api/counselsession/service/CounselSessionService.java index 5d837ef6..ce593dfe 100644 --- a/src/main/java/com/springboot/api/counselsession/service/CounselSessionService.java +++ b/src/main/java/com/springboot/api/counselsession/service/CounselSessionService.java @@ -301,35 +301,45 @@ public List getSessionDatesByYearAndMonth(int year, int month) { @Cacheable(value = "sessionStats") @Transactional(readOnly = true) public CounselSessionStatRes getSessionStats() { - long totalSessionCount = calculateTotalSessionCount(); - Long counseleeCount = counselSessionRepository.countDistinctCounseleeForCurrentMonth(); - long totalCaringMessageCount = counselSessionRepository.count(); - double counselHours = calculateCounselHoursForThisMonth(); + long counselHoursThisMonth = calculateCounselHoursForThisMonth(); + Long counseleeCountForThisMonth = counselSessionRepository.countDistinctCounseleeForCurrentMonth(); + long medicationCounselCountThisYear = calculateMedicationCounselCountThisYear(); + long counselorCountThisYear = calculateCounselorCountThisYear(); return CounselSessionStatRes.builder() - .totalSessionCount(totalSessionCount) - .counseleeCountForThisMonth(counseleeCount) - .totalCaringMessageCount(totalCaringMessageCount) - .counselHoursForThisMonth((long) counselHours) + .counselHoursThisMonth(counselHoursThisMonth) + .counseleeCountForThisMonth(counseleeCountForThisMonth) + .medicationCounselCountThisYear(medicationCounselCountThisYear) + .counselorCountThisYear(counselorCountThisYear) .build(); } - private long calculateTotalSessionCount() { - return counselSessionRepository.countByStatus(ScheduleStatus.COMPLETED); + private long calculateMedicationCounselCountThisYear() { + int currentYear = LocalDateTime.now().getYear(); + return medicationCounselRepository.countByCreatedDatetimeBetween( + LocalDateTime.of(currentYear, 1, 1, 0, 0, 0), + LocalDateTime.of(currentYear + 1, 1, 1, 0, 0, 0) + ); } - private double calculateCounselHoursForThisMonth() { + private long calculateCounselorCountThisYear() { + int currentYear = LocalDateTime.now().getYear(); + Long count = counselSessionRepository.countDistinctCounselorsByCompletedSessionsInYear(currentYear); + return count != null ? count : 0L; + } + + private long calculateCounselHoursForThisMonth() { int year = LocalDateTime.now().getYear(); int month = LocalDateTime.now().getMonthValue(); List completedSessions = counselSessionRepository .findCompletedSessionsByYearAndMonth(year, month); return completedSessions.stream() - .mapToDouble(session -> { + .mapToLong(session -> { Duration duration = Duration.between( session.getStartDateTime(), session.getEndDateTime()); - return duration.toMinutes() / 60.0; + return (long) (duration.toMinutes() / 60.0); }) .sum(); }