Add can SMS question, fix error handling of client ID

This commit is contained in:
Eli Ribble 2026-04-14 15:11:07 +00:00
parent 84db38c985
commit 5527731e83
No known key found for this signature in database
6 changed files with 68 additions and 45 deletions

View file

@ -9,22 +9,27 @@ import (
"github.com/Gleipnir-Technology/nidus-sync/db/models"
"github.com/aarondl/opt/omit"
"github.com/google/uuid"
"github.com/rs/zerolog/log"
)
func EnsureClient(ctx context.Context, client uuid.UUID, user_agent string) error {
_, err := models.PublicreportClients.Query(
models.SelectWhere.PublicreportClients.UUID.EQ(client),
).One(ctx, db.PGInstance.BobDB)
if err != nil {
if err.Error() == "sql: no rows in result set" {
if err == nil {
log.Debug().Str("client", client.String()).Msg("already exists")
return nil
}
} else if err != nil && err.Error() != "sql: no rows in result set" {
return fmt.Errorf("failed existing client %s: %w", client.String(), err)
}
models.PublicreportClients.Insert(&models.PublicreportClientSetter{
_, err = models.PublicreportClients.Insert(&models.PublicreportClientSetter{
Created: omit.From(time.Now()),
UserAgent: omit.From(user_agent),
UUID: omit.From(client),
}).One(ctx, db.PGInstance.BobDB)
if err != nil {
return fmt.Errorf("insert client: %w", err)
}
log.Debug().Str("client", client.String()).Str("ua", user_agent).Msg("Created client")
return nil
}

View file

@ -49,7 +49,10 @@ func (res *complianceR) ByID(ctx context.Context, r *http.Request, query QueryPa
}
func (res *complianceR) Create(ctx context.Context, r *http.Request, n publicreportComplianceForm) (*compliance, *nhttp.ErrorWithStatus) {
user_agent := r.Header.Get("User-Agent")
platform.EnsureClient(ctx, n.ClientID, user_agent)
err := platform.EnsureClient(ctx, n.ClientID, user_agent)
if err != nil {
return nil, nhttp.NewError("Failed to ensure client: %w", err)
}
setter_report := models.PublicreportReportSetter{
//AddressID: omitnull.From(latlng.Cell.String()),
AddressGid: omit.From(""),

View file

@ -15,6 +15,7 @@ type publicreportNotificationR struct {
}
type publicreportNotification struct {
CanSMS bool `json:"can_sms"`
Consent bool `json:"consent"`
Email string `json:"email"`
Name string `json:"name"`

View file

@ -32,16 +32,12 @@ type nuisance struct {
ID string `json:"id"`
URI string `json:"uri"`
}
type Locator struct {
Address types.Address `schema:"address"`
Location types.Location `schema:"location"`
}
type nuisanceForm struct {
Address types.Address `schema:"address"`
AdditionalInfo string `schema:"additional-info"`
ClientID uuid.UUID `schema:"client_id" json:"client_id"`
Duration string `schema:"duration"`
Location types.Location `schema:"location"`
Locator Locator `schema:"locator"`
MapZoom string `schema:"map-zoom"`
SourceStagnant bool `schema:"source-stagnant"`
SourceContainer bool `schema:"source-container"`
@ -56,7 +52,10 @@ type nuisanceForm struct {
func (res *nuisanceR) Create(ctx context.Context, r *http.Request, n nuisanceForm) (*nuisance, *nhttp.ErrorWithStatus) {
user_agent := r.Header.Get("User-Agent")
platform.EnsureClient(ctx, n.ClientID, user_agent)
err := platform.EnsureClient(ctx, n.ClientID, user_agent)
if err != nil {
return nil, nhttp.NewError("Failed to ensure client: %w", err)
}
duration := enums.PublicreportNuisancedurationtypeNone
is_location_frontyard := slices.Contains(n.SourceLocations, "frontyard")
is_location_backyard := slices.Contains(n.SourceLocations, "backyard")
@ -64,7 +63,7 @@ func (res *nuisanceR) Create(ctx context.Context, r *http.Request, n nuisanceFor
is_location_pool := slices.Contains(n.SourceLocations, "pool-area")
is_location_other := slices.Contains(n.SourceLocations, "other")
err := duration.Scan(n.Duration)
err = duration.Scan(n.Duration)
if err != nil {
log.Warn().Err(err).Str("duration_str", n.Duration).Msg("Failed to interpret 'duration'")
}
@ -74,19 +73,14 @@ func (res *nuisanceR) Create(ctx context.Context, r *http.Request, n nuisanceFor
if err != nil {
return nil, nhttp.NewError("Failed to extract image uploads: %w", err)
}
address := platform.Address{
GID: n.Locator.Address.GID,
Raw: n.Locator.Address.Raw,
}
accuracy := float32(0.0)
if n.Location.Accuracy != nil {
accuracy = *n.Location.Accuracy
}
log.Info().Str("address.raw", address.Raw).Str("address.gid", address.GID).Msg("making nuisance")
setter_report := models.PublicreportReportSetter{
//AddressID: omitnull.From(latlng.Cell.String()),
AddressGid: omit.From(address.GID),
AddressRaw: omit.From(address.Raw),
AddressGid: omit.From(n.Address.GID),
AddressRaw: omit.From(n.Address.Raw),
ClientUUID: omitnull.From(n.ClientID),
Created: omit.From(time.Now()),
//H3cell: omitnull.From(latlng.Cell.String()),
@ -100,6 +94,7 @@ func (res *nuisanceR) Create(ctx context.Context, r *http.Request, n nuisanceFor
ReporterEmail: omit.From(""),
ReporterName: omit.From(""),
ReporterPhone: omit.From(""),
ReporterPhoneCanSMS: omit.From(true),
ReportType: omit.From(enums.PublicreportReporttypeNuisance),
Status: omit.From(enums.PublicreportReportstatustypeReported),
}
@ -121,7 +116,7 @@ func (res *nuisanceR) Create(ctx context.Context, r *http.Request, n nuisanceFor
TodEvening: omit.From(n.TODEvening),
TodNight: omit.From(n.TODNight),
}
report, err := platform.PublicReportNuisanceCreate(ctx, setter_report, setter_nuisance, n.Location, address, uploads)
report, err := platform.PublicReportNuisanceCreate(ctx, setter_report, setter_nuisance, n.Location, n.Address, uploads)
if err != nil {
return nil, nhttp.NewError("create nuisance report: %w", err)
}

View file

@ -38,7 +38,7 @@ type waterForm struct {
AccessGate bool `schema:"access-gate"`
AccessLocked bool `schema:"access-locked"`
AccessOther bool `schema:"access-other"`
Address string `schema:"address"`
Address types.Address `schema:"address"`
AddressGID string `schema:"address-gid"`
ClientID uuid.UUID `schema:"client_id" json:"client_id"`
Comments string `schema:"comments"`
@ -49,7 +49,6 @@ type waterForm struct {
IsReporterConfidential bool `schema:"reporter-confidential"`
IsReporter_owner bool `schema:"property-ownership"`
Location types.Location `schema:"location"`
Locator Locator `schema:"locator"`
OwnerEmail string `schema:"owner-email"`
OwnerName string `schema:"owner-name"`
OwnerPhone string `schema:"owner-phone"`
@ -57,7 +56,10 @@ type waterForm struct {
func (res *waterR) Create(ctx context.Context, r *http.Request, w waterForm) (*water, *nhttp.ErrorWithStatus) {
user_agent := r.Header.Get("User-Agent")
platform.EnsureClient(ctx, w.ClientID, user_agent)
err := platform.EnsureClient(ctx, w.ClientID, user_agent)
if err != nil {
return nil, nhttp.NewError("Failed to ensure client: %w", err)
}
uploads, err := html.ExtractImageUploads(r)
log.Info().Int("len", len(uploads)).Msg("extracted water uploads")
@ -65,17 +67,13 @@ func (res *waterR) Create(ctx context.Context, r *http.Request, w waterForm) (*w
return nil, nhttp.NewError("Failed to extract image uploads: %w", err)
}
address := platform.Address{
GID: w.AddressGID,
Raw: w.Address,
}
accuracy := float32(0.0)
if w.Location.Accuracy != nil {
accuracy = *w.Location.Accuracy
}
setter_report := models.PublicreportReportSetter{
AddressGid: omit.From(address.GID),
AddressRaw: omit.From(address.Raw),
AddressGid: omit.From(w.Address.GID),
AddressRaw: omit.From(w.Address.Raw),
ClientUUID: omitnull.From(w.ClientID),
Created: omit.From(time.Now()),
//H3cell: omitnull.From(geospatial.Cell.String()),
@ -89,6 +87,7 @@ func (res *waterR) Create(ctx context.Context, r *http.Request, w waterForm) (*w
ReporterEmail: omit.From(""),
ReporterName: omit.From(""),
ReporterPhone: omit.From(""),
ReporterPhoneCanSMS: omit.From(true),
ReportType: omit.From(enums.PublicreportReporttypeWater),
Status: omit.From(enums.PublicreportReportstatustypeReported),
}
@ -111,7 +110,7 @@ func (res *waterR) Create(ctx context.Context, r *http.Request, w waterForm) (*w
OwnerPhone: omit.From(w.OwnerPhone),
//ReportID omit.Val[int32]
}
report, err := platform.PublicReportWaterCreate(ctx, setter_report, setter_water, w.Location, address, uploads)
report, err := platform.PublicReportWaterCreate(ctx, setter_report, setter_water, w.Location, w.Address, uploads)
if err != nil {
return nil, nhttp.NewError("Failed to save new report: %w", err)
}

View file

@ -125,6 +125,24 @@
</div>
</div>
<div class="form-check mb-3 form-check">
<input
v-model="formData.can_sms"
class="form-check-input"
id="can_sms"
type="checkbox"
/>
<label class="form-check-label" for="can_sms">
This phone number can receive text messages
<i
class="bi bi-info-circle-fill text-primary ms-1"
data-bs-toggle="tooltip"
data-bs-placement="top"
title="By 'text messages' we specifically mean SMS/MMS messages. If it's a mobile or cellular phone, it should work. If it's a home or office phone, it may not."
></i>
</label>
</div>
<div class="form-check mb-3 form-check">
<input
v-model="formData.consent"
@ -262,10 +280,11 @@ import { useStorePublicReport } from "@/store/publicreport";
import type { District, PublicReport } from "@/type/api";
interface FormData {
name: string;
can_sms: boolean;
consent: boolean;
email: string;
phone: string;
consent: boolean;
name: string;
notification: boolean;
subscribe: boolean;
}
@ -277,10 +296,11 @@ interface Props {
const props = defineProps<Props>();
const formData = ref<FormData>({
name: "",
can_sms: true,
consent: true,
email: "",
phone: "",
consent: true,
name: "",
notification: false,
subscribe: false,
});