Update measurements
This commit is contained in:
parent
44387aa14b
commit
2295a6e84c
2 changed files with 101 additions and 6 deletions
|
@ -120,6 +120,7 @@ func Handler() http.Handler {
|
||||||
r{handleUpdater(characteristicService), "PUT", "/characteristics/{Id:.+}"},
|
r{handleUpdater(characteristicService), "PUT", "/characteristics/{Id:.+}"},
|
||||||
r{handleLister(measurementService), "GET", "/measurements"},
|
r{handleLister(measurementService), "GET", "/measurements"},
|
||||||
r{handleGetter(measurementService), "GET", "/measurements/{Id:.+}"},
|
r{handleGetter(measurementService), "GET", "/measurements/{Id:.+}"},
|
||||||
|
r{handleUpdater(measurementService), "PUT", "/measurements/{Id:.+}"},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, route := range routes {
|
for _, route := range routes {
|
||||||
|
|
106
measurements.go
106
measurements.go
|
@ -34,17 +34,17 @@ func (m *MeasurementBase) PreUpdate(e modl.SqlExecutor) error {
|
||||||
|
|
||||||
type MeasurementService struct{}
|
type MeasurementService struct{}
|
||||||
|
|
||||||
// There are three types of supported measurements: fixed-test, free-text,
|
// There are three types of supported measurements: fixed-text, free-text,
|
||||||
// & numerical. The table has a constraint that will allow one or the other
|
// & numerical. The table has a constraint that will allow at most one
|
||||||
// for a particular combination of strain & characteristic, but not both.
|
// for a particular combination of strain & characteristic.
|
||||||
// MeasurementBase is what the DB expects to see for inserts/updates
|
// MeasurementBase is what the DB expects to see for inserts/updates
|
||||||
type MeasurementBase struct {
|
type MeasurementBase struct {
|
||||||
Id int64 `json:"id,omitempty"`
|
Id int64 `json:"id,omitempty"`
|
||||||
StrainId int64 `db:"strain_id" json:"strain"`
|
StrainId int64 `db:"strain_id" json:"strain"`
|
||||||
CharacteristicId int64 `db:"characteristic_id" json:"characteristic"`
|
CharacteristicId int64 `db:"characteristic_id" json:"characteristic"`
|
||||||
TextMeasurementTypeId NullInt64 `db:"text_measurement_type_id" json:"-"`
|
TextMeasurementTypeId NullInt64 `db:"text_measurement_type_id" json:"-"`
|
||||||
TxtValue NullString `db:"txt_value" json:"txtValue"`
|
TxtValue NullString `db:"txt_value" json:"-"`
|
||||||
NumValue NullFloat64 `db:"num_value" json:"numValue"`
|
NumValue NullFloat64 `db:"num_value" json:"-"`
|
||||||
ConfidenceInterval NullFloat64 `db:"confidence_interval" json:"confidenceInterval"`
|
ConfidenceInterval NullFloat64 `db:"confidence_interval" json:"confidenceInterval"`
|
||||||
UnitTypeId NullInt64 `db:"unit_type_id" json:"-"`
|
UnitTypeId NullInt64 `db:"unit_type_id" json:"-"`
|
||||||
Notes NullString `db:"notes" json:"notes"`
|
Notes NullString `db:"notes" json:"notes"`
|
||||||
|
@ -57,12 +57,58 @@ type MeasurementBase struct {
|
||||||
|
|
||||||
type Measurement struct {
|
type Measurement struct {
|
||||||
*MeasurementBase
|
*MeasurementBase
|
||||||
TextMeasurementType NullString `db:"text_measurement_type_name" json:"textMeasurementType"`
|
TextMeasurementType NullString `db:"text_measurement_type_name" json:"-"`
|
||||||
UnitType NullString `db:"unit_type_name" json:"unitType"`
|
UnitType NullString `db:"unit_type_name" json:"unitType"`
|
||||||
TestMethod NullString `db:"test_method_name" json:"testMethod"`
|
TestMethod NullString `db:"test_method_name" json:"testMethod"`
|
||||||
CanEdit bool `db:"-" json:"canEdit"`
|
CanEdit bool `db:"-" json:"canEdit"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type FakeMeasurement Measurement
|
||||||
|
|
||||||
|
func (m *Measurement) MarshalJSON() ([]byte, error) {
|
||||||
|
fm := FakeMeasurement(*m)
|
||||||
|
return json.Marshal(struct {
|
||||||
|
*FakeMeasurement
|
||||||
|
Value string `json:"value"`
|
||||||
|
}{
|
||||||
|
FakeMeasurement: &fm,
|
||||||
|
Value: m.Value(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Measurement) UnmarshalJSON(b []byte) error {
|
||||||
|
var measurement struct {
|
||||||
|
FakeMeasurement
|
||||||
|
Value interface{} `json:"value"`
|
||||||
|
}
|
||||||
|
if err := json.Unmarshal(b, &measurement); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
switch v := measurement.Value.(type) {
|
||||||
|
case string:
|
||||||
|
// Test if actually a lookup
|
||||||
|
id, err := getTextMeasurementTypeId(v)
|
||||||
|
if err != nil {
|
||||||
|
if err == sql.ErrNoRows {
|
||||||
|
measurement.TxtValue = NullString{sql.NullString{String: v, Valid: true}}
|
||||||
|
} else {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
measurement.TextMeasurementTypeId = NullInt64{sql.NullInt64{Int64: id, Valid: true}}
|
||||||
|
}
|
||||||
|
case int64:
|
||||||
|
measurement.NumValue = NullFloat64{sql.NullFloat64{Float64: float64(v), Valid: true}}
|
||||||
|
case float64:
|
||||||
|
measurement.NumValue = NullFloat64{sql.NullFloat64{Float64: v, Valid: true}}
|
||||||
|
}
|
||||||
|
|
||||||
|
*m = Measurement(measurement.FakeMeasurement)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (m *Measurement) Value() string {
|
func (m *Measurement) Value() string {
|
||||||
if m.TextMeasurementType.Valid {
|
if m.TextMeasurementType.Valid {
|
||||||
return m.TextMeasurementType.String
|
return m.TextMeasurementType.String
|
||||||
|
@ -100,6 +146,12 @@ func (m *MeasurementsPayload) marshal() ([]byte, error) {
|
||||||
return json.Marshal(m)
|
return json.Marshal(m)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s MeasurementService) unmarshal(b []byte) (entity, error) {
|
||||||
|
var mj MeasurementPayload
|
||||||
|
err := json.Unmarshal(b, &mj)
|
||||||
|
return &mj, err
|
||||||
|
}
|
||||||
|
|
||||||
type MeasurementListOptions struct {
|
type MeasurementListOptions struct {
|
||||||
ListOptions
|
ListOptions
|
||||||
Strains []int64 `schema:"strain_ids"`
|
Strains []int64 `schema:"strain_ids"`
|
||||||
|
@ -162,6 +214,38 @@ func (m MeasurementService) get(id int64, genus string, claims *Claims) (entity,
|
||||||
return &payload, nil
|
return &payload, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s MeasurementService) update(id int64, e *entity, genus string, claims *Claims) *appError {
|
||||||
|
payload := (*e).(*MeasurementPayload)
|
||||||
|
payload.Measurement.UpdatedBy = claims.Sub
|
||||||
|
payload.Measurement.Id = id
|
||||||
|
|
||||||
|
if payload.Measurement.TextMeasurementType.Valid {
|
||||||
|
id, err := getTextMeasurementTypeId(payload.Measurement.TextMeasurementType.String)
|
||||||
|
if err != nil {
|
||||||
|
return newJSONError(err, http.StatusInternalServerError)
|
||||||
|
}
|
||||||
|
payload.Measurement.TextMeasurementTypeId.Int64 = id
|
||||||
|
payload.Measurement.TextMeasurementTypeId.Valid = true
|
||||||
|
}
|
||||||
|
|
||||||
|
count, err := DBH.Update(payload.Measurement.MeasurementBase)
|
||||||
|
if err != nil {
|
||||||
|
return newJSONError(err, http.StatusInternalServerError)
|
||||||
|
}
|
||||||
|
if count != 1 {
|
||||||
|
return newJSONError(ErrStrainNotUpdated, http.StatusBadRequest)
|
||||||
|
}
|
||||||
|
|
||||||
|
measurement, err := getMeasurement(id, genus, claims)
|
||||||
|
if err != nil {
|
||||||
|
return newJSONError(err, http.StatusInternalServerError)
|
||||||
|
}
|
||||||
|
|
||||||
|
payload.Measurement = measurement
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func listMeasurements(opt MeasurementListOptions, claims *Claims) (*Measurements, error) {
|
func listMeasurements(opt MeasurementListOptions, claims *Claims) (*Measurements, error) {
|
||||||
var vals []interface{}
|
var vals []interface{}
|
||||||
|
|
||||||
|
@ -257,3 +341,13 @@ func characteristicOptsFromMeasurements(opt MeasurementListOptions) (*ListOption
|
||||||
func strainOptsFromMeasurements(opt MeasurementListOptions) (*ListOptions, error) {
|
func strainOptsFromMeasurements(opt MeasurementListOptions) (*ListOptions, error) {
|
||||||
return &ListOptions{Genus: opt.Genus, Ids: opt.Strains}, nil
|
return &ListOptions{Genus: opt.Genus, Ids: opt.Strains}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getTextMeasurementTypeId(val string) (int64, error) {
|
||||||
|
var id int64
|
||||||
|
q := `SELECT id FROM text_measurement_types WHERE text_measurement_name=$1;`
|
||||||
|
|
||||||
|
if err := DBH.SelectOne(&id, q, val); err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return id, nil
|
||||||
|
}
|
||||||
|
|
Reference in a new issue