@@ -134,37 +134,42 @@ func (s *Service) Overview(ctx context.Context, f Filter) (*storage.UsageOvervie
134134 return s .store .BuildUsageOverview (ctx , f .toStorage (), prices )
135135}
136136
137- // Health returns the month -sized request matrix and the available month list .
138- func (s * Service ) Health (ctx context.Context , f Filter , monthKey string , now time.Time ) (* storage.UsageHealthMatrix , error ) {
139- start , err := parseMonth ( monthKey , now )
137+ // Health returns the year -sized request matrix and optional selected-day detail .
138+ func (s * Service ) Health (ctx context.Context , f Filter , yearKey , dayKey string , now time.Time ) (* storage.UsageHealthMatrix , error ) {
139+ year , err := parseYear ( yearKey , now )
140140 if err != nil {
141141 return nil , err
142142 }
143- end := start .AddDate (0 , 1 , 0 )
143+ start := time .Date (year , time .January , 1 , 0 , 0 , 0 , 0 , time .Local )
144+ end := start .AddDate (1 , 0 , 0 )
144145 sf := f .toStorage ()
145146 sf .Range = ""
146147 sf .Start = time.Time {}
147148 sf .End = time.Time {}
148149
149- months , err := s .store .ListUsageEventMonths (ctx , sf )
150+ years , err := s .store .ListUsageEventYears (ctx , sf )
150151 if err != nil {
151152 return nil , err
152153 }
153- month := start .Format ("2006-01" )
154154 localNow := now .In (time .Local )
155- currentMonth := time .Date (localNow .Year (), localNow .Month (), 1 , 0 , 0 , 0 , 0 , time .Local ).Format ("2006-01" )
156- months = ensureMonthOption (ensureMonthOption (months , month ), currentMonth )
155+ years = ensureYearOption (ensureYearOption (years , year ), localNow .Year ())
157156
158- grid , err := s .store .BuildUsageHealthGrid (ctx , sf , start , end )
157+ days , err := s .store .BuildUsageHealthDays (ctx , sf , start , end )
158+ if err != nil {
159+ return nil , err
160+ }
161+ selectedDay , detail , err := s .healthDetail (ctx , sf , start , end , dayKey )
159162 if err != nil {
160163 return nil , err
161164 }
162165 return & storage.UsageHealthMatrix {
163- Month : month ,
164- Start : start ,
165- End : end ,
166- Grid : grid ,
167- Months : months ,
166+ Year : year ,
167+ Start : start ,
168+ End : end ,
169+ Days : days ,
170+ Years : years ,
171+ SelectedDay : selectedDay ,
172+ Detail : detail ,
168173 }, nil
169174}
170175
@@ -358,27 +363,54 @@ func parseTime(in string) (time.Time, error) {
358363 return time.Time {}, fmt .Errorf ("unrecognized time %q" , in )
359364}
360365
361- func parseMonth (in string , now time.Time ) (time.Time , error ) {
366+ func (s * Service ) healthDetail (ctx context.Context , f storage.UsageFilter , yearStart , yearEnd time.Time , dayKey string ) (string , [][]storage.HealthCell , error ) {
367+ dayKey = strings .TrimSpace (dayKey )
368+ if dayKey == "" {
369+ return "" , nil , nil
370+ }
371+ day , err := parseDay (dayKey )
372+ if err != nil {
373+ return "" , nil , err
374+ }
375+ if day .Before (yearStart ) || ! day .Before (yearEnd ) {
376+ return "" , nil , fmt .Errorf ("day %q is outside selected year" , dayKey )
377+ }
378+ detail , err := s .store .BuildUsageHealthDetail (ctx , f , day )
379+ if err != nil {
380+ return "" , nil , err
381+ }
382+ return day .Format ("2006-01-02" ), detail , nil
383+ }
384+
385+ func parseYear (in string , now time.Time ) (int , error ) {
362386 in = strings .TrimSpace (in )
363387 if in == "" {
364- local := now .In (time .Local )
365- return time .Date (local .Year (), local .Month (), 1 , 0 , 0 , 0 , 0 , time .Local ), nil
388+ return now .In (time .Local ).Year (), nil
389+ }
390+ t , err := time .ParseInLocation ("2006" , in , time .Local )
391+ if err != nil {
392+ return 0 , fmt .Errorf ("parse year: %w" , err )
366393 }
367- t , err := time .ParseInLocation ("2006-01" , in , time .Local )
394+ return t .Year (), nil
395+ }
396+
397+ func parseDay (in string ) (time.Time , error ) {
398+ in = strings .TrimSpace (in )
399+ t , err := time .ParseInLocation ("2006-01-02" , in , time .Local )
368400 if err != nil {
369- return time.Time {}, fmt .Errorf ("parse month : %w" , err )
401+ return time.Time {}, fmt .Errorf ("parse day : %w" , err )
370402 }
371- return time .Date (t .Year (), t .Month (), 1 , 0 , 0 , 0 , 0 , time .Local ), nil
403+ return time .Date (t .Year (), t .Month (), t . Day () , 0 , 0 , 0 , 0 , time .Local ), nil
372404}
373405
374- func ensureMonthOption ( months []storage.UsageHealthMonth , month string ) []storage.UsageHealthMonth {
375- for _ , m := range months {
376- if m . Month == month {
377- return months
406+ func ensureYearOption ( years []storage.UsageHealthYear , year int ) []storage.UsageHealthYear {
407+ for _ , y := range years {
408+ if y . Year == year {
409+ return years
378410 }
379411 }
380- out := append ([]storage.UsageHealthMonth {{ Month : month }}, months ... )
381- sort .SliceStable (out , func (i , j int ) bool { return out [i ].Month > out [j ].Month })
412+ out := append ([]storage.UsageHealthYear {{ Year : year }}, years ... )
413+ sort .SliceStable (out , func (i , j int ) bool { return out [i ].Year > out [j ].Year })
382414 return out
383415}
384416
0 commit comments