55import org .devkor .apu .saerok_server .domain .stat .core .entity .DailyStat ;
66import org .devkor .apu .saerok_server .domain .stat .core .entity .StatMetric ;
77import org .devkor .apu .saerok_server .domain .stat .core .repository .DailyStatRepository ;
8+ import org .devkor .apu .saerok_server .global .shared .exception .BadRequestException ;
89import org .springframework .stereotype .Service ;
910import org .springframework .transaction .annotation .Transactional ;
1011
12+ import java .time .LocalDate ;
13+ import java .time .format .DateTimeParseException ;
1114import java .util .*;
1215
1316@ Service
@@ -17,12 +20,13 @@ public class StatQueryService {
1720
1821 private final DailyStatRepository dailyRepo ;
1922
20- public StatSeriesResponse getSeries (List <StatMetric > metrics ) {
23+ public StatSeriesResponse getSeries (List <StatMetric > metrics , String period ) {
2124 if (metrics == null || metrics .isEmpty ()) return StatSeriesResponse .empty ();
2225
26+ LocalDateRange range = parsePeriod (period );
2327 List <StatSeriesResponse .Series > out = new ArrayList <>();
2428 for (StatMetric m : metrics ) {
25- List <DailyStat > rows = dailyRepo .findSeriesByMetric (m );
29+ List <DailyStat > rows = dailyRepo .findSeriesByMetric (m , range . startDate (), range . endDate () );
2630
2731 if (m == StatMetric .BIRD_ID_RESOLUTION_STATS_28D ) {
2832 var minSeries = new StatSeriesResponse .ComponentSeries (
@@ -60,4 +64,41 @@ public StatSeriesResponse getSeries(List<StatMetric> metrics) {
6064 private static Number numberOrNull (Object o ) {
6165 return (o instanceof Number n ) ? n : null ;
6266 }
67+
68+ private LocalDateRange parsePeriod (String period ) {
69+ if (period == null || period .isBlank ()) {
70+ return LocalDateRange .empty ();
71+ }
72+
73+ String [] tokens = period .split ("," );
74+ if (tokens .length != 2 ) {
75+ throw new BadRequestException ("period 파라미터는 '시작일,종료일' 형식이어야 합니다." );
76+ }
77+
78+ LocalDate start = parseDate (tokens [0 ].trim (), "시작일" );
79+ LocalDate end = parseDate (tokens [1 ].trim (), "종료일" );
80+
81+ if (start != null && end != null && end .isBefore (start )) {
82+ throw new BadRequestException ("period 파라미터는 종료일이 시작일보다 빠를 수 없습니다." );
83+ }
84+
85+ return new LocalDateRange (start , end );
86+ }
87+
88+ private LocalDate parseDate (String value , String label ) {
89+ if (value == null || value .isBlank ()) {
90+ return null ;
91+ }
92+ try {
93+ return LocalDate .parse (value );
94+ } catch (DateTimeParseException e ) {
95+ throw new BadRequestException (label + "은 yyyy-MM-dd 형식이어야 합니다." );
96+ }
97+ }
98+
99+ private record LocalDateRange (LocalDate startDate , LocalDate endDate ) {
100+ private static LocalDateRange empty () {
101+ return new LocalDateRange (null , null );
102+ }
103+ }
63104}
0 commit comments