From 9e3d12ae2ae8d364cd698248dd2bd778c8c08d09 Mon Sep 17 00:00:00 2001 From: Eli Ribble Date: Thu, 20 Nov 2025 15:24:54 +0000 Subject: [PATCH] Add treatment and inspection history to a source --- html.go | 75 +++++++++++++++++++++++++------------- model_conversion.go | 31 ++++++++++++++-- templates/source.html | 84 +++++++------------------------------------ 3 files changed, 92 insertions(+), 98 deletions(-) diff --git a/html.go b/html.go index f3036821..6dea3ce3 100644 --- a/html.go +++ b/html.go @@ -18,6 +18,7 @@ import ( "github.com/Gleipnir-Technology/nidus-sync/models" "github.com/aarondl/opt/null" //"github.com/riverqueue/river/rivershared/util/slogutil" + //"github.com/rs/zerolog/log" "github.com/stephenafamo/bob/dialect/psql" "github.com/stephenafamo/bob/dialect/psql/sm" "github.com/uber/h3-go/v4" @@ -120,9 +121,11 @@ type ContentSignin struct { } type ContentSignup struct{} type ContentSource struct { - MapData ComponentMap - Source *BreedingSourceDetail - User User + Inspections []Inspection + MapData ComponentMap + Source *BreedingSourceDetail + Treatments []Treatment + User User } type LatLng struct { Lat float64 @@ -493,7 +496,18 @@ func htmlSource(w http.ResponseWriter, r *http.Request, user *models.User, id st respondError(w, "Failed to get source", err, http.StatusInternalServerError) return } + inspections, err := inspectionsBySource(r.Context(), org, id) + if err != nil { + respondError(w, "Failed to get inspections", err, http.StatusInternalServerError) + return + } + treatments, err := treatmentsBySource(r.Context(), org, id) + if err != nil { + respondError(w, "Failed to get treatments", err, http.StatusInternalServerError) + return + } data := ContentSource{ + Inspections: inspections, MapData: ComponentMap{ Center: LatLng{ Lat: s.GeometryY, @@ -511,8 +525,9 @@ func htmlSource(w http.ResponseWriter, r *http.Request, user *models.User, id st }, Zoom: 13, }, - Source: s, - User: userContent, + Source: s, + Treatments: treatments, + User: userContent, } renderOrError(w, source, data) @@ -666,6 +681,21 @@ func renderOrError(w http.ResponseWriter, template BuiltTemplate, context interf buf.WriteTo(w) } +func treatmentsBySource(ctx context.Context, org *models.Organization, sourceID string) ([]Treatment, error) { + var results []Treatment + rows, err := org.FSTreatments( + sm.Where( + models.FSTreatments.Columns.Pointlocid.EQ(psql.Arg(sourceID)), + ), + sm.OrderBy("enddatetime"), + ).All(ctx, PGInstance.BobDB) + if err != nil { + return results, fmt.Errorf("Failed to query rows: %w", err) + } + //log.Info().Int("row count", len(rows)).Msg("Getting treatments") + return toTemplateTreatment(rows) +} + func treatmentsByCell(ctx context.Context, org *models.Organization, c h3.Cell) ([]Treatment, error) { var results []Treatment boundary, err := c.Boundary() @@ -683,15 +713,7 @@ func treatmentsByCell(ctx context.Context, org *models.Organization, c h3.Cell) if err != nil { return results, fmt.Errorf("Failed to query rows: %w", err) } - for _, r := range rows { - results = append(results, Treatment{ - Date: *fsTimestampToTime(r.Enddatetime), - LocationID: r.Pointlocid.GetOr("none"), - Notes: r.Comments.GetOr("none"), - Product: r.Product.GetOr("none"), - }) - } - return results, nil + return toTemplateTreatment(rows) } func inspectionsByCell(ctx context.Context, org *models.Organization, c h3.Cell) ([]Inspection, error) { var results []Inspection @@ -711,16 +733,21 @@ func inspectionsByCell(ctx context.Context, org *models.Organization, c h3.Cell) if err != nil { return results, fmt.Errorf("Failed to query rows: %w", err) } - for _, r := range rows { - results = append(results, Inspection{ - Action: r.Actiontaken.GetOr("none"), - Date: *fsTimestampToTime(r.Enddatetime), - Notes: r.Comments.GetOr("none"), - Location: r.Locationname.GetOr("none"), - LocationID: r.Pointlocid.GetOr(""), - }) + return toTemplateInspection(rows) +} +func inspectionsBySource(ctx context.Context, org *models.Organization, sourceID string) ([]Inspection, error) { + var results []Inspection + + rows, err := org.FSMosquitoinspections( + sm.Where( + models.FSMosquitoinspections.Columns.Pointlocid.EQ(psql.Arg(sourceID)), + ), + sm.OrderBy("enddatetime").Desc(), + ).All(ctx, PGInstance.BobDB) + if err != nil { + return results, fmt.Errorf("Failed to query rows: %w", err) } - return results, nil + return toTemplateInspection(rows) } func breedingSourcesByCell(ctx context.Context, org *models.Organization, c h3.Cell) ([]BreedingSourceSummary, error) { var results []BreedingSourceSummary @@ -765,5 +792,5 @@ func sourceByGlobalId(ctx context.Context, org *models.Organization, id string) if err != nil { return nil, fmt.Errorf("Failed to get point location: %w", err) } - return ConvertToDisplayModel(row), nil + return toTemplateBreedingSource(row), nil } diff --git a/model_conversion.go b/model_conversion.go index 62611d01..a74e2e7c 100644 --- a/model_conversion.go +++ b/model_conversion.go @@ -72,8 +72,35 @@ type BreedingSourceDetail struct { Comments string `json:"comments"` } -// ConvertToDisplayModel transforms the DB model into the display model -func ConvertToDisplayModel(source *models.FSPointlocation) *BreedingSourceDetail { +func toTemplateTreatment(rows models.FSTreatmentSlice) ([]Treatment, error) { + var results []Treatment + for _, r := range rows { + results = append(results, Treatment{ + Date: *fsTimestampToTime(r.Enddatetime), + LocationID: r.Pointlocid.GetOr("none"), + Notes: r.Comments.GetOr("none"), + Product: r.Product.GetOr("none"), + }) + } + return results, nil +} + +func toTemplateInspection(rows models.FSMosquitoinspectionSlice) ([]Inspection, error) { + var results []Inspection + for _, r := range rows { + results = append(results, Inspection{ + Action: r.Actiontaken.GetOr("none"), + Date: *fsTimestampToTime(r.Enddatetime), + Notes: r.Comments.GetOr("none"), + Location: r.Locationname.GetOr("none"), + LocationID: r.Pointlocid.GetOr(""), + }) + } + return results, nil +} + +// toTemplateBreedingSource transforms the DB model into the display model +func toTemplateBreedingSource(source *models.FSPointlocation) *BreedingSourceDetail { // Helper function to convert unix timestamp to time.Time toTime := func(val null.Val[int64]) time.Time { v, ok := val.Get() diff --git a/templates/source.html b/templates/source.html index c9b19e75..345844d2 100644 --- a/templates/source.html +++ b/templates/source.html @@ -244,53 +244,17 @@ + {{ range .Treatments }} - 04/16/2023 - Bacillus thuringiensis israelensis (Bti) + {{.Date|timeSince}} + {{.Product}} On time - Applied larvicide to standing water. - - - 04/02/2023 - Methoprene - On time - Applied to ditch with extended release formula. - - - 03/18/2023 - Bacillus sphaericus - -1 day - Preemptive treatment before rain event. - - - 03/01/2023 - Bacillus thuringiensis israelensis (Bti) - +3 days - Delayed due to weather conditions. - - - 02/15/2023 - Methoprene - On time - Regular treatment cycle. + {{.Notes}} + {{ end }} - - @@ -303,42 +267,18 @@ Inspection Date - Inspector - Larvae Present - Comments + Action + Notes + {{ range .Inspections }} - 04/15/2023 - J. Smith - Yes - Moderate larvae presence, treatment recommended. - - - 04/01/2023 - M. Johnson - Yes - High larvae count, immediate treatment needed. - - - 03/17/2023 - J. Smith - No - No larvae observed, previous treatment effective. - - - 03/03/2023 - R. Williams - Yes - Low larvae count, monitoring recommended. - - - 02/14/2023 - M. Johnson - Yes - Moderate larvae count, treatment scheduled. + {{.Date|timeSince}} + {{.Action}} + {{.Notes}} + {{ end }}