package api import ( "database/sql" "net/http" "strconv" "strings" ) type PlansAPI struct { marketing *sql.DB } func PlansHandler(marketing *sql.DB) http.Handler { api := &PlansAPI{marketing: marketing} return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { p := strings.TrimPrefix(r.URL.Path, "/api/plans") if r.Method == http.MethodGet && p == "" { api.list(w, r) return } w.WriteHeader(http.StatusNotFound) }) } func (a *PlansAPI) list(w http.ResponseWriter, r *http.Request) { resellerParam := r.URL.Query().Get("reseller") if resellerParam == "" { resellerParam = r.URL.Query().Get("reseller_id") } q := r.URL.Query().Get("q") limitStr := r.URL.Query().Get("limit") limit := 2000 if limitStr != "" { if n, err := strconv.Atoi(limitStr); err == nil && n > 0 && n <= 10000 { limit = n } } resellers := []string{} for _, s := range strings.Split(resellerParam, ",") { s = strings.TrimSpace(s) if s != "" { resellers = append(resellers, s) } } if len(resellers) == 0 { ok(w, r, []map[string]interface{}{}) return } ph := strings.Repeat("?,", len(resellers)) ph = strings.TrimSuffix(ph, ",") sql1 := "SELECT id, COALESCE(title,'') AS title FROM plan WHERE reseller_id IN (" + ph + ")" args := []interface{}{} for _, v := range resellers { args = append(args, v) } if q != "" { sql1 += " AND (CAST(id AS CHAR) LIKE ? OR title LIKE ?)" like := "%" + q + "%" args = append(args, like, like) } sql1 += " ORDER BY id ASC LIMIT ?" args = append(args, limit) rows, err := a.marketing.Query(sql1, args...) if err != nil { fail(w, r, http.StatusInternalServerError, err.Error()) return } defer rows.Close() out := []map[string]interface{}{} for rows.Next() { var id sql.NullInt64 var title sql.NullString if err := rows.Scan(&id, &title); err != nil { continue } if !id.Valid { continue } m := map[string]interface{}{"id": id.Int64, "title": title.String} out = append(out, m) } ok(w, r, out) }