Fix creation of signal from a communication report

I had broken this when altering the signal model to always require a
location
This commit is contained in:
Eli Ribble 2026-03-20 18:03:32 +00:00
parent f09533c742
commit aa94cce2ad
No known key found for this signature in database
3 changed files with 66 additions and 54 deletions

View file

@ -5,13 +5,11 @@ import (
"fmt"
"time"
"github.com/Gleipnir-Technology/bob"
"github.com/Gleipnir-Technology/bob/dialect/psql"
"github.com/Gleipnir-Technology/bob/dialect/psql/um"
"github.com/Gleipnir-Technology/nidus-sync/db"
"github.com/Gleipnir-Technology/nidus-sync/db/enums"
"github.com/Gleipnir-Technology/nidus-sync/db/models"
"github.com/Gleipnir-Technology/nidus-sync/platform/geocode"
"github.com/Gleipnir-Technology/nidus-sync/platform/geom"
"github.com/aarondl/opt/omit"
"github.com/aarondl/opt/omitnull"
@ -63,42 +61,3 @@ func LeadCreate(ctx context.Context, user User, signal_id int32, site_id int32,
txn.Commit(ctx)
return &lead.ID, nil
}
func siteFromAddress(ctx context.Context, txn bob.Tx, user User, address_id int32) (*models.Site, error) {
site, err := models.Sites.Query(
models.SelectWhere.Sites.AddressID.EQ(address_id),
models.SelectWhere.Sites.OrganizationID.EQ(user.Organization.ID()),
).One(ctx, txn)
if err == nil {
return site, nil
}
if err.Error() != "sql: no rows in result set" {
return nil, fmt.Errorf("query site: %w", err)
}
return SiteCreate(ctx, txn, user, address_id)
}
func siteFromAddressRaw(ctx context.Context, txn bob.Tx, user User, address string) (*models.Site, error) {
// Geocode
geo, err := geocode.GeocodeRaw(ctx, user.Organization.model, address)
if err != nil {
return nil, fmt.Errorf("geocode: %w", err)
}
a, err := geocode.EnsureAddress(ctx, txn, geo.Address, geo.Location)
if err != nil {
return nil, fmt.Errorf("ensure address: %w", err)
}
return siteFromAddress(ctx, txn, user, a.ID)
}
func siteFromLocation(ctx context.Context, txn bob.Tx, user User, location Location) (*models.Site, error) {
// Reverse geocode at the location
resp, err := geocode.ReverseGeocode(ctx, location)
if err != nil {
return nil, fmt.Errorf("reverse geocode: %w", err)
}
// Ensure we have an address at that newly created location
a, err := geocode.EnsureAddress(ctx, txn, resp.Address, resp.Location)
if err != nil {
return nil, fmt.Errorf("ensure address: %w", err)
}
return siteFromAddress(ctx, txn, user, a.ID)
}

View file

@ -20,8 +20,8 @@ import (
//"github.com/Gleipnir-Technology/nidus-sync/platform/geom"
"github.com/aarondl/opt/omit"
"github.com/aarondl/opt/omitnull"
"github.com/rs/zerolog/log"
"github.com/stephenafamo/scan"
//"github.com/rs/zerolog/log"
)
type Signal struct {
@ -56,22 +56,33 @@ func SignalCreateFromPublicreport(ctx context.Context, user User, report_id stri
// At this point we have a report. We need to decide where to put it based on either the address or
// the location.
var site_id int32
var location string
if report.AddressID.IsValue() {
site, err := siteFromAddress(ctx, txn, user, report.AddressID.MustGet())
address_id := report.AddressID.MustGet()
address, err := models.FindAddress(ctx, txn, address_id)
if err != nil {
return nil, fmt.Errorf("find address: %w", err)
}
site, err := siteFromAddress(ctx, txn, user, address_id)
if err != nil {
return nil, fmt.Errorf("site from address: %w", err)
}
site_id = site.ID
lat := address.LocationX.GetOr(0.0)
lng := address.LocationX.GetOr(0.0)
location = fmt.Sprintf("POINT(%f %f)", lng, lat)
} else if report.LocationLatitude.IsValue() && report.LocationLongitude.IsValue() {
lat := report.LocationLatitude.MustGet()
lng := report.LocationLongitude.MustGet()
site, err := siteFromLocation(ctx, txn, user, Location{
Latitude: report.LocationLatitude.MustGet(),
Longitude: report.LocationLongitude.MustGet(),
Latitude: lat,
Longitude: lng,
})
if err != nil {
return nil, fmt.Errorf("site from address: %w", err)
}
site_id = site.ID
location = fmt.Sprintf("POINT(%f %f)", lng, lat)
} else if report.AddressRaw != "" {
// At this point we don't have an address, and we don't have GPS
// We'll try geocoding and creating an address from that.
@ -79,11 +90,18 @@ func SignalCreateFromPublicreport(ctx context.Context, user User, report_id stri
if err != nil {
return nil, fmt.Errorf("site from address: %w", err)
}
address, err := models.FindAddress(ctx, txn, site.AddressID)
if err != nil {
return nil, fmt.Errorf("find address from raw: %w", err)
}
site_id = site.ID
lat := address.LocationX.GetOr(0.0)
lng := address.LocationX.GetOr(0.0)
location = fmt.Sprintf("POINT(%f %f)", lng, lat)
} else {
// We have no structured address, no GPS, no unstructued address.
// There's really nothing we can make this lead from and have it be meaningful
return nil, errors.New("Refusing to create a lead with no location data.")
return nil, errors.New("Refusing to create a signal with no location data.")
}
var signal_type enums.Signaltype
@ -95,6 +113,7 @@ func SignalCreateFromPublicreport(ctx context.Context, user User, report_id stri
default:
return nil, fmt.Errorf("Unrecognized report type %s", string(report.ReportType))
}
log.Debug().Str("location", location).Msg("inserting signal")
signal, err := models.Signals.Insert(&models.SignalSetter{
Addressed: omitnull.FromPtr[time.Time](nil),
Addressor: omitnull.FromPtr[int32](nil),
@ -102,6 +121,7 @@ func SignalCreateFromPublicreport(ctx context.Context, user User, report_id stri
Creator: omit.From(int32(user.ID)),
// ID
OrganizationID: omit.From(int32(user.Organization.ID())),
Location: omit.From(location),
Species: omitnull.FromPtr[enums.Mosquitospecies](nil),
SiteID: omitnull.From(site_id),
Title: omit.From[string](""),
@ -160,13 +180,7 @@ func SignalList(ctx context.Context, user User, limit int) ([]Signal, error) {
sm.Where(psql.Quote("signal", "addressed").IsNull()),
sm.Limit(limit),
), scan.StructMapper[Signal]())
/*
rows, err := models.Signals.Query(
models.SelectWhere.Signals.OrganizationID.EQ(org.ID()),
sm.OrderBy("created").Desc(),
).All(ctx, db.PGInstance.BobDB)
*/
log.Debug().Int("len", len(rows)).Msg("got signals")
if err != nil {
return nil, fmt.Errorf("failed to get signals: %w", err)
}

View file

@ -13,6 +13,7 @@ import (
"github.com/Gleipnir-Technology/nidus-sync/db"
"github.com/Gleipnir-Technology/nidus-sync/db/models"
nhttp "github.com/Gleipnir-Technology/nidus-sync/http"
"github.com/Gleipnir-Technology/nidus-sync/platform/geocode"
"github.com/aarondl/opt/omit"
"github.com/aarondl/opt/omitnull"
"github.com/stephenafamo/scan"
@ -62,3 +63,41 @@ func SiteCreate(ctx context.Context, txn bob.Tx, user User, address_id int32) (*
Version: omit.From(int32(1)),
}).One(ctx, txn)
}
func siteFromAddress(ctx context.Context, txn bob.Tx, user User, address_id int32) (*models.Site, error) {
site, err := models.Sites.Query(
models.SelectWhere.Sites.AddressID.EQ(address_id),
models.SelectWhere.Sites.OrganizationID.EQ(user.Organization.ID()),
).One(ctx, txn)
if err == nil {
return site, nil
}
if err.Error() != "sql: no rows in result set" {
return nil, fmt.Errorf("query site: %w", err)
}
return SiteCreate(ctx, txn, user, address_id)
}
func siteFromAddressRaw(ctx context.Context, txn bob.Tx, user User, address string) (*models.Site, error) {
// Geocode
geo, err := geocode.GeocodeRaw(ctx, user.Organization.model, address)
if err != nil {
return nil, fmt.Errorf("geocode: %w", err)
}
a, err := geocode.EnsureAddress(ctx, txn, geo.Address, geo.Location)
if err != nil {
return nil, fmt.Errorf("ensure address: %w", err)
}
return siteFromAddress(ctx, txn, user, a.ID)
}
func siteFromLocation(ctx context.Context, txn bob.Tx, user User, location Location) (*models.Site, error) {
// Reverse geocode at the location
resp, err := geocode.ReverseGeocode(ctx, location)
if err != nil {
return nil, fmt.Errorf("reverse geocode: %w", err)
}
// Ensure we have an address at that newly created location
a, err := geocode.EnsureAddress(ctx, txn, resp.Address, resp.Location)
if err != nil {
return nil, fmt.Errorf("ensure address: %w", err)
}
return siteFromAddress(ctx, txn, user, a.ID)
}