diff --git a/species.go b/species.go index da63a0c..d97117b 100644 --- a/species.go +++ b/species.go @@ -56,6 +56,7 @@ type SpeciesMeta struct { type ManySpeciesPayload struct { Species *ManySpecies `json:"species"` + Strains *Strains `json:"strains"` Meta *SpeciesMeta `json:"meta"` } @@ -115,11 +116,49 @@ func (s SpeciesService) list(val *url.Values, claims Claims) (entity, *appError) return nil, newJSONError(err, http.StatusInternalServerError) } - meta := SpeciesMeta{CanAdd: canAdd(claims)} - payload := ManySpeciesPayload{Species: &species, Meta: &meta} + strains_opt, err := strainOptsFromSpecies(opt) + if err != nil { + return nil, newJSONError(err, http.StatusInternalServerError) + } + + strains, err := listStrains(*strains_opt) + if err != nil { + return nil, newJSONError(err, http.StatusInternalServerError) + } + + payload := ManySpeciesPayload{ + Species: &species, + Strains: strains, + Meta: &SpeciesMeta{CanAdd: canAdd(claims)}, + } + return &payload, nil } +func strainOptsFromSpecies(opt ListOptions) (*ListOptions, error) { + relatedStrainIds := make([]int64, 0) + + if opt.Ids == nil { + q := `SELECT DISTINCT st.id + FROM strains st + INNER JOIN species sp ON sp.id=st.species_id + INNER JOIN genera g ON g.id=sp.genus_id AND LOWER(g.genus_name)=LOWER($1);` + if err := DBH.Select(&relatedStrainIds, q, opt.Genus); err != nil { + return nil, err + } + } else { + var vals []interface{} + var count int64 = 1 + q := fmt.Sprintf("SELECT DISTINCT id FROM strains WHERE %s;", valsIn("species_id", opt.Ids, &vals, &count)) + + if err := DBH.Select(&relatedStrainIds, q, vals...); err != nil { + return nil, err + } + } + + return &ListOptions{Genus: opt.Genus, Ids: relatedStrainIds}, nil +} + func (s SpeciesService) get(id int64, genus string) (entity, *appError) { var species Species q := `SELECT sp.*, g.genus_name, array_agg(st.id) AS strains, diff --git a/strains.go b/strains.go index b556bfc..4e2ea88 100644 --- a/strains.go +++ b/strains.go @@ -83,7 +83,18 @@ func (s StrainService) list(val *url.Values, claims Claims) (entity, *appError) return nil, newJSONError(err, http.StatusInternalServerError) } + strains, err := listStrains(opt) + + if err != nil { + return nil, newJSONError(err, http.StatusInternalServerError) + } + + return strains, nil +} + +func listStrains(opt ListOptions) (*Strains, error) { var vals []interface{} + sql := `SELECT st.*, array_agg(m.id) AS measurements, COUNT(m) AS total_measurements, rank() OVER (ORDER BY sp.species_name ASC, st.type_strain ASC, st.strain_name ASC) AS sort_order FROM strains st @@ -109,7 +120,7 @@ func (s StrainService) list(val *url.Values, claims Claims) (entity, *appError) strains := make(Strains, 0) err := DBH.Select(&strains, sql, vals...) if err != nil { - return nil, newJSONError(err, http.StatusInternalServerError) + return nil, err } return &strains, nil }