2026-04-03 22:04:22 +00:00
|
|
|
package resource
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"context"
|
|
|
|
|
"net/http"
|
|
|
|
|
"slices"
|
|
|
|
|
"time"
|
|
|
|
|
|
2026-05-07 10:39:17 +00:00
|
|
|
modelpublicreport "github.com/Gleipnir-Technology/nidus-sync/db/gen/nidus-sync/publicreport/model"
|
|
|
|
|
//tablepublicreport "github.com/Gleipnir-Technology/nidus-sync/db/gen/nidus-sync/publicreport/table"
|
|
|
|
|
//querypublicreport "github.com/Gleipnir-Technology/nidus-sync/db/query/publicreport"
|
2026-04-03 22:04:22 +00:00
|
|
|
"github.com/Gleipnir-Technology/nidus-sync/html"
|
|
|
|
|
nhttp "github.com/Gleipnir-Technology/nidus-sync/http"
|
|
|
|
|
"github.com/Gleipnir-Technology/nidus-sync/platform"
|
2026-04-09 17:21:35 +00:00
|
|
|
"github.com/Gleipnir-Technology/nidus-sync/platform/types"
|
2026-04-14 14:50:28 +00:00
|
|
|
"github.com/google/uuid"
|
2026-04-14 15:31:10 +00:00
|
|
|
"github.com/gorilla/mux"
|
2026-04-03 22:04:22 +00:00
|
|
|
"github.com/rs/zerolog/log"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
func Nuisance(r *router) *nuisanceR {
|
|
|
|
|
return &nuisanceR{
|
|
|
|
|
router: r,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type nuisanceR struct {
|
|
|
|
|
router *router
|
|
|
|
|
}
|
|
|
|
|
type nuisance struct {
|
2026-04-08 17:49:32 +00:00
|
|
|
District string `json:"district"`
|
2026-04-14 15:24:21 +00:00
|
|
|
PublicID string `json:"public_id"`
|
2026-04-08 17:49:32 +00:00
|
|
|
URI string `json:"uri"`
|
2026-04-03 22:04:22 +00:00
|
|
|
}
|
2026-04-09 17:21:35 +00:00
|
|
|
type nuisanceForm struct {
|
2026-04-14 15:11:07 +00:00
|
|
|
Address types.Address `schema:"address"`
|
2026-04-09 17:21:35 +00:00
|
|
|
AdditionalInfo string `schema:"additional-info"`
|
2026-04-14 14:50:28 +00:00
|
|
|
ClientID uuid.UUID `schema:"client_id" json:"client_id"`
|
2026-04-09 17:21:35 +00:00
|
|
|
Duration string `schema:"duration"`
|
|
|
|
|
Location types.Location `schema:"location"`
|
|
|
|
|
MapZoom string `schema:"map-zoom"`
|
|
|
|
|
SourceStagnant bool `schema:"source-stagnant"`
|
|
|
|
|
SourceContainer bool `schema:"source-container"`
|
|
|
|
|
SourceDescription string `schema:"source-description"`
|
|
|
|
|
SourceGutters bool `schema:"source-gutters"`
|
|
|
|
|
SourceLocations []string `schema:"source-location"`
|
|
|
|
|
TODEarly bool `schema:"tod-early"`
|
|
|
|
|
TODDay bool `schema:"tod-day"`
|
|
|
|
|
TODEvening bool `schema:"tod-evening"`
|
|
|
|
|
TODNight bool `schema:"tod-night"`
|
2026-04-03 22:04:22 +00:00
|
|
|
}
|
|
|
|
|
|
2026-04-28 06:36:55 +00:00
|
|
|
func (res *nuisanceR) ByID(ctx context.Context, r *http.Request, u platform.User, query QueryParams) (*types.PublicReportNuisance, *nhttp.ErrorWithStatus) {
|
2026-04-28 07:12:12 +00:00
|
|
|
return res.byID(ctx, r, false)
|
2026-04-28 06:36:55 +00:00
|
|
|
}
|
|
|
|
|
func (res *nuisanceR) ByIDPublic(ctx context.Context, r *http.Request, query QueryParams) (*types.PublicReportNuisance, *nhttp.ErrorWithStatus) {
|
2026-04-28 07:12:12 +00:00
|
|
|
return res.byID(ctx, r, true)
|
2026-04-14 15:31:10 +00:00
|
|
|
}
|
2026-04-03 22:04:22 +00:00
|
|
|
func (res *nuisanceR) Create(ctx context.Context, r *http.Request, n nuisanceForm) (*nuisance, *nhttp.ErrorWithStatus) {
|
2026-04-14 14:50:28 +00:00
|
|
|
user_agent := r.Header.Get("User-Agent")
|
2026-04-14 15:11:07 +00:00
|
|
|
err := platform.EnsureClient(ctx, n.ClientID, user_agent)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, nhttp.NewError("Failed to ensure client: %w", err)
|
|
|
|
|
}
|
2026-05-07 10:39:17 +00:00
|
|
|
duration := modelpublicreport.Nuisancedurationtype_None
|
2026-04-03 22:04:22 +00:00
|
|
|
is_location_frontyard := slices.Contains(n.SourceLocations, "frontyard")
|
|
|
|
|
is_location_backyard := slices.Contains(n.SourceLocations, "backyard")
|
|
|
|
|
is_location_garden := slices.Contains(n.SourceLocations, "garden")
|
|
|
|
|
is_location_pool := slices.Contains(n.SourceLocations, "pool-area")
|
|
|
|
|
is_location_other := slices.Contains(n.SourceLocations, "other")
|
|
|
|
|
|
2026-04-14 15:11:07 +00:00
|
|
|
err = duration.Scan(n.Duration)
|
2026-04-03 22:04:22 +00:00
|
|
|
if err != nil {
|
|
|
|
|
log.Warn().Err(err).Str("duration_str", n.Duration).Msg("Failed to interpret 'duration'")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uploads, err := html.ExtractImageUploads(r)
|
2026-04-09 17:21:35 +00:00
|
|
|
log.Info().Int("len", len(uploads)).Msg("extracted nuisance uploads")
|
2026-04-03 22:04:22 +00:00
|
|
|
if err != nil {
|
|
|
|
|
return nil, nhttp.NewError("Failed to extract image uploads: %w", err)
|
|
|
|
|
}
|
2026-04-09 17:21:35 +00:00
|
|
|
accuracy := float32(0.0)
|
|
|
|
|
if n.Location.Accuracy != nil {
|
|
|
|
|
accuracy = *n.Location.Accuracy
|
2026-04-03 22:04:22 +00:00
|
|
|
}
|
2026-05-07 10:39:17 +00:00
|
|
|
setter_report := modelpublicreport.Report{
|
|
|
|
|
//AddressID: omitnull.From(...),
|
|
|
|
|
AddressGid: "",
|
|
|
|
|
AddressRaw: "",
|
|
|
|
|
ClientUUID: &n.ClientID,
|
|
|
|
|
Created: time.Now(),
|
2026-04-03 22:04:22 +00:00
|
|
|
//H3cell: omitnull.From(latlng.Cell.String()),
|
2026-05-07 10:39:17 +00:00
|
|
|
LatlngAccuracyType: modelpublicreport.Accuracytype_Browser,
|
|
|
|
|
LatlngAccuracyValue: accuracy,
|
2026-04-03 22:04:22 +00:00
|
|
|
//Location: omitnull.From(fmt.Sprintf("ST_GeometryFromText(Point(%s %s))", longitude, latitude)),
|
2026-05-07 10:39:17 +00:00
|
|
|
Location: nil,
|
|
|
|
|
MapZoom: float32(0.0),
|
|
|
|
|
//OrganizationID: ,
|
|
|
|
|
//PublicID:
|
|
|
|
|
ReporterEmail: "",
|
|
|
|
|
ReporterName: "",
|
|
|
|
|
ReporterPhone: "",
|
|
|
|
|
ReporterPhoneCanSms: true,
|
|
|
|
|
ReportType: modelpublicreport.Reporttype_Nuisance,
|
|
|
|
|
Status: modelpublicreport.Reportstatustype_Reported,
|
2026-04-03 22:04:22 +00:00
|
|
|
}
|
2026-05-07 10:39:17 +00:00
|
|
|
setter_nuisance := modelpublicreport.Nuisance{
|
|
|
|
|
AdditionalInfo: n.AdditionalInfo,
|
|
|
|
|
Duration: duration,
|
|
|
|
|
IsLocationBackyard: is_location_backyard,
|
|
|
|
|
IsLocationFrontyard: is_location_frontyard,
|
|
|
|
|
IsLocationGarden: is_location_garden,
|
|
|
|
|
IsLocationOther: is_location_other,
|
|
|
|
|
IsLocationPool: is_location_pool,
|
2026-04-03 22:04:22 +00:00
|
|
|
//ReportID omit.Val[int32]
|
2026-05-07 10:39:17 +00:00
|
|
|
SourceContainer: n.SourceContainer,
|
|
|
|
|
SourceDescription: n.SourceDescription,
|
|
|
|
|
SourceGutter: n.SourceGutters,
|
|
|
|
|
SourceStagnant: n.SourceStagnant,
|
|
|
|
|
TodDay: n.TODDay,
|
|
|
|
|
TodEarly: n.TODEarly,
|
|
|
|
|
TodEvening: n.TODEvening,
|
|
|
|
|
TodNight: n.TODNight,
|
2026-04-03 22:04:22 +00:00
|
|
|
}
|
2026-04-14 15:11:07 +00:00
|
|
|
report, err := platform.PublicReportNuisanceCreate(ctx, setter_report, setter_nuisance, n.Location, n.Address, uploads)
|
2026-04-08 14:40:27 +00:00
|
|
|
if err != nil {
|
|
|
|
|
return nil, nhttp.NewError("create nuisance report: %w", err)
|
|
|
|
|
}
|
2026-04-28 06:53:58 +00:00
|
|
|
uri, err := res.router.IDStrToURI("publicreport.ByIDGetPublic", report.PublicID)
|
2026-04-08 17:49:32 +00:00
|
|
|
if err != nil {
|
|
|
|
|
return nil, nhttp.NewError("generate uri: %w", err)
|
|
|
|
|
}
|
|
|
|
|
district_uri, err := res.router.IDToURI("district.ByIDGet", int(report.OrganizationID))
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, nhttp.NewError("generate district uri: %w", err)
|
|
|
|
|
}
|
2026-04-03 22:04:22 +00:00
|
|
|
return &nuisance{
|
2026-04-08 17:49:32 +00:00
|
|
|
District: district_uri,
|
2026-04-14 15:24:21 +00:00
|
|
|
PublicID: report.PublicID,
|
2026-04-08 17:49:32 +00:00
|
|
|
URI: uri,
|
2026-04-03 22:04:22 +00:00
|
|
|
}, nil
|
|
|
|
|
}
|
2026-04-28 07:12:12 +00:00
|
|
|
func (res *nuisanceR) byID(ctx context.Context, r *http.Request, is_public bool) (*types.PublicReportNuisance, *nhttp.ErrorWithStatus) {
|
|
|
|
|
vars := mux.Vars(r)
|
|
|
|
|
public_id := vars["id"]
|
|
|
|
|
if public_id == "" {
|
|
|
|
|
return nil, nhttp.NewBadRequest("You must provid an ID")
|
|
|
|
|
}
|
2026-04-28 14:55:53 +00:00
|
|
|
report, err := platform.PublicReportByIDNuisance(ctx, public_id, is_public)
|
2026-04-28 07:12:12 +00:00
|
|
|
if err != nil {
|
|
|
|
|
return nil, nhttp.NewError("get report: %w", err)
|
|
|
|
|
}
|
|
|
|
|
populateDistrictURI(&report.PublicReport, res.router)
|
|
|
|
|
populateReportURI(&report.PublicReport, res.router, is_public)
|
|
|
|
|
return report, nil
|
|
|
|
|
}
|