Create address records from nuisance report data if provided

This commit is contained in:
Eli Ribble 2026-03-09 19:09:42 +00:00
parent 5af93abbb9
commit d2eecdef90
No known key found for this signature in database
2 changed files with 83 additions and 4 deletions

View file

@ -32,6 +32,63 @@ func InitializeStadia(key string) {
client = stadia.NewStadiaMaps(key)
}
// Ensure the provided address exists. If it doesn't add it to the database.
func EnsureAddress(ctx context.Context, txn bob.Tx, a types.Address, l types.Location) (*models.Address, error) {
address, err := models.Addresses.Query(
models.SelectWhere.Addresses.Country.EQ(a.CountryEnum()),
models.SelectWhere.Addresses.Locality.EQ(a.Locality),
models.SelectWhere.Addresses.Number.EQ(a.Number),
models.SelectWhere.Addresses.PostalCode.EQ(a.PostalCode),
models.SelectWhere.Addresses.Region.EQ(a.Region),
models.SelectWhere.Addresses.Street.EQ(a.Street),
models.SelectWhere.Addresses.Unit.EQ(a.Unit),
).One(ctx, txn)
if err == nil {
return address, nil
}
cell, err := h3utils.GetCell(l.Longitude, l.Latitude, 15)
if err != nil {
return nil, fmt.Errorf("failed to convert lat %f lng %f to h3 cell", l.Longitude, l.Latitude)
}
type _row struct {
ID int32 `db:"id"`
}
created := time.Now()
row, err := bob.One(ctx, txn, psql.Insert(
im.Into("address", "country", "created", "h3cell", "id", "locality", "location", "number_", "postal_code", "region", "street", "unit"),
im.Values(
psql.Arg(a.Country),
psql.Arg(created),
psql.Arg(cell),
psql.Raw("DEFAULT"),
psql.Arg(a.Locality),
psql.F("ST_Point", l.Longitude, l.Latitude, 4326),
psql.Arg(a.Number),
psql.Arg(a.PostalCode),
psql.Arg(a.Region),
psql.Arg(a.Street),
psql.Raw("''"),
),
im.Returning("id"),
), scan.StructMapper[_row]())
if err != nil {
return nil, fmt.Errorf("insert: %w", err)
}
return &models.Address{
Country: a.CountryEnum(),
Created: created,
H3cell: "",
ID: row.ID,
Locality: a.Locality,
Location: "",
PostalCode: a.PostalCode,
Street: a.Street,
Unit: a.Unit,
Region: a.Region,
Number: a.Number,
}, nil
}
// Either get an address that matches, or create a new address. Either way, return an address
// This will make a call to a structured geocode service, so it's slow.
func EnsureAddressWithGeocode(ctx context.Context, txn bob.Tx, org *models.Organization, a types.Address) (*models.Address, error) {

View file

@ -13,7 +13,9 @@ import (
"github.com/Gleipnir-Technology/nidus-sync/db/enums"
"github.com/Gleipnir-Technology/nidus-sync/db/models"
"github.com/Gleipnir-Technology/nidus-sync/html"
"github.com/Gleipnir-Technology/nidus-sync/platform/geocode"
"github.com/Gleipnir-Technology/nidus-sync/platform/report"
"github.com/Gleipnir-Technology/nidus-sync/platform/types"
"github.com/aarondl/opt/omit"
"github.com/aarondl/opt/omitnull"
"github.com/rs/zerolog/log"
@ -80,7 +82,7 @@ func postNuisance(w http.ResponseWriter, r *http.Request) {
return
}
additional_info := r.PostFormValue("additional-info")
address := r.PostFormValue("address")
address_raw := r.PostFormValue("address")
address_country := r.PostFormValue("address-country")
address_locality := r.PostFormValue("address-locality")
address_number := r.PostFormValue("address-number")
@ -129,7 +131,6 @@ func postNuisance(w http.ResponseWriter, r *http.Request) {
is_location_pool = true
}
//log.Debug().Bool("is_location_backyard", is_location_backyard).Bool("is_location_frontyard", is_location_frontyard).Bool("is_location_garden", is_location_garden).Bool("is_location_other", is_location_other).Bool("is_location_pool", is_location_pool).Msg("parsed")
public_id, err := report.GenerateReportID()
if err != nil {
respondError(w, "Failed to create report public ID", err, http.StatusInternalServerError)
@ -149,6 +150,23 @@ func postNuisance(w http.ResponseWriter, r *http.Request) {
}
defer txn.Rollback(ctx)
// If we've got an address_country value it was set by geocoding so we should save it
var address *models.Address
if address_country != "" && latlng.Latitude != nil && latlng.Longitude != nil {
address, err = geocode.EnsureAddress(ctx, txn, types.Address{
Country: address_country,
Locality: address_locality,
Number: address_number,
PostalCode: address_postal_code,
Region: address_region,
Street: address_street,
Unit: "",
}, types.Location{
Latitude: *latlng.Latitude,
Longitude: *latlng.Longitude,
})
}
uploads, err := extractImageUploads(r)
log.Info().Int("len", len(uploads)).Msg("extracted uploads")
if err != nil {
@ -167,8 +185,9 @@ func postNuisance(w http.ResponseWriter, r *http.Request) {
}
setter := models.PublicreportNuisanceSetter{
AdditionalInfo: omit.From(additional_info),
AddressRaw: omit.From(address),
AdditionalInfo: omit.From(additional_info),
//AddressID: omitnull.From(geospatial.Cell.String()),
AddressRaw: omit.From(address_raw),
AddressCountry: omit.From(address_country),
AddressNumber: omit.From(address_number),
AddressLocality: omit.From(address_locality),
@ -203,6 +222,9 @@ func postNuisance(w http.ResponseWriter, r *http.Request) {
TodEvening: omit.From(tod_evening),
TodNight: omit.From(tod_night),
}
if address != nil {
setter.AddressID = omitnull.From(address.ID)
}
nuisance, err := models.PublicreportNuisances.Insert(&setter).One(ctx, txn)
if err != nil {
respondError(w, "Failed to create database record", err, http.StatusInternalServerError)