From 78fffd6eb17efb50d7568beb0927675903cd4b3f Mon Sep 17 00:00:00 2001 From: andig Date: Sun, 13 Aug 2023 15:09:19 +0200 Subject: [PATCH] Make csv export more flexible (#9309) --- core/db/session.go | 29 ++++++++++-------------- server/http_session_handler.go | 41 ++++++++++++++++------------------ 2 files changed, 31 insertions(+), 39 deletions(-) diff --git a/core/db/session.go b/core/db/session.go index b0dd0879a..cbdebacbe 100644 --- a/core/db/session.go +++ b/core/db/session.go @@ -57,7 +57,6 @@ func (t *Sessions) writeHeader(ctx context.Context, ww *csv.Writer) error { caption, err := localizer.Localize(&locale.Config{ MessageID: "sessions.csv." + strings.ToLower(f.Name()), }) - if err != nil { if csv != "" { caption = csv @@ -79,28 +78,24 @@ func (t *Sessions) writeRow(ww *csv.Writer, mp *message.Printer, r Session) erro continue } - var val string digits := 3 if format := f.Tag("format"); format == "int" { digits = 0 } - switch v := f.Value().(type) { - case float64: - val = mp.Sprint(number.Decimal(v, number.NoSeparator(), number.MaxFractionDigits(digits))) - case time.Time: - if !v.IsZero() { - val = v.Local().Format("2006-01-02 15:04:05") - } - default: - if rv := reflect.ValueOf(v); rv.Kind() == reflect.Ptr { - if pv := reflect.Indirect(rv); pv.CanFloat() && !rv.IsNil() { - val = mp.Sprint(number.Decimal(pv.Float(), number.NoSeparator(), number.MaxFractionDigits(digits))) - } - break - } + var val string - val = fmt.Sprintf("%v", f.Value()) + if rv := reflect.ValueOf(f.Value()); !(rv.Kind() == reflect.Pointer && rv.IsNil()) { + switch v := f.Value().(type) { + case float64, *float64: + val = mp.Sprint(number.Decimal(v, number.NoSeparator(), number.MaxFractionDigits(digits))) + case time.Time: + if !v.IsZero() { + val = v.Local().Format("2006-01-02 15:04:05") + } + default: + val = fmt.Sprintf("%v", f.Value()) + } } row = append(row, val) diff --git a/server/http_session_handler.go b/server/http_session_handler.go index b077aa79e..1e5c64628 100644 --- a/server/http_session_handler.go +++ b/server/http_session_handler.go @@ -7,7 +7,7 @@ import ( "fmt" "math" "net/http" - "strconv" + "strings" "github.com/evcc-io/evcc/api" "github.com/evcc-io/evcc/core/db" @@ -35,34 +35,31 @@ func sessionHandler(w http.ResponseWriter, r *http.Request) { return } - var res db.Sessions - year := r.URL.Query().Get("year") - month := r.URL.Query().Get("month") + var ( + res db.Sessions + cond []string + args []any + ) + + push := func(field, val string) { + cond = append(cond, field) + args = append(args, val) + } filename := "session" + if year := r.URL.Query().Get("year"); year != "" { + filename += "-" + year + push("STRFTIME('%Y', created) LIKE ?", year) - fmtYear := "%" - fmtMonth := "%" - - if year != "" { - fmtYear = year - filename += "-" + fmtYear - - if month != "" { - iMonth, err := strconv.Atoi(month) - if err != nil { - jsonError(w, http.StatusBadRequest, err) - return - } - - fmtMonth = fmt.Sprintf("%02d", iMonth) - filename += "." + fmtMonth + if month := fmt.Sprintf("%02s", r.URL.Query().Get("month")); month != "00" { + filename += "-" + month + push("STRFTIME('%m', created) LIKE ?", month) } } // TODO support other databases than Sqlite - whereQuery := "charged_kwh>=0.05 AND strftime('%Y', created) LIKE ? AND strftime('%m', created) LIKE ?" - if txn := dbserver.Instance.Where(whereQuery, fmtYear, fmtMonth).Order("created DESC").Find(&res); txn.Error != nil { + query := strings.Join(append([]string{"charged_kwh>=0.05"}, cond...), " AND ") + if txn := dbserver.Instance.Where(query, args...).Order("created DESC").Find(&res); txn.Error != nil { jsonError(w, http.StatusInternalServerError, txn.Error) return }