nidus-sync/resource/publicreport_compliance.go

243 lines
9.5 KiB
Go
Raw Normal View History

2026-04-09 23:38:20 +00:00
package resource
import (
"context"
"net/http"
"time"
"github.com/Gleipnir-Technology/nidus-sync/db/enums"
"github.com/Gleipnir-Technology/nidus-sync/db/models"
"github.com/aarondl/opt/omit"
"github.com/aarondl/opt/omitnull"
//"github.com/Gleipnir-Technology/nidus-sync/html"
2026-04-09 23:38:20 +00:00
nhttp "github.com/Gleipnir-Technology/nidus-sync/http"
"github.com/Gleipnir-Technology/nidus-sync/platform"
"github.com/Gleipnir-Technology/nidus-sync/platform/types"
"github.com/google/uuid"
"github.com/gorilla/mux"
2026-04-13 20:42:03 +00:00
"github.com/rs/zerolog/log"
2026-04-09 23:38:20 +00:00
)
func PublicReportCompliance(r *router) *complianceR {
2026-04-09 23:38:20 +00:00
return &complianceR{
router: r,
}
}
type complianceR struct {
router *router
}
type publicreportComplianceForm struct {
AccessInstructions omit.Val[string] `schema:"access_instructions" json:"access_instructions"`
Address omit.Val[types.Address] `schema:"address" json:"address"`
AvailabilityNotes omit.Val[string] `schema:"availability_notes" json:"availability_notes"`
ClientID uuid.UUID `schema:"client_id" json:"client_id"`
Comments omit.Val[string] `schema:"comments" json:"comments"`
District omit.Val[string] `schema:"district" json:"district"`
GateCode omit.Val[string] `schema:"gate_code" json:"gate_code"`
HasDog omitnull.Val[bool] `schema:"has_dog" json:"has_dog"`
Location omit.Val[types.Location] `schema:"location" json:"location"`
MailerID omit.Val[string] `schema:"mailer_id" json:"mailer_id"`
PermissionType omit.Val[enums.Permissionaccesstype] `schema:"permission_type" json:"permission_type"`
Reporter omit.Val[types.Contact] `schema:"reporter" json:"reporter"`
ReportPhoneCanSMS omitnull.Val[bool] `schema:"report_phone_can_text" json:"report_phone_can_text"`
WantsScheduled omitnull.Val[bool] `schema:"wants_scheduled" json:"wants_scheduled"`
}
func (res *complianceR) ByID(ctx context.Context, r *http.Request, u platform.User, query QueryParams) (*types.PublicReportCompliance, *nhttp.ErrorWithStatus) {
return res.ByIDPublic(ctx, r, query)
}
func (res *complianceR) ByIDPublic(ctx context.Context, r *http.Request, query QueryParams) (*types.PublicReportCompliance, *nhttp.ErrorWithStatus) {
vars := mux.Vars(r)
public_id := vars["id"]
if public_id == "" {
return nil, nhttp.NewBadRequest("You must provid an ID")
}
report, err := platform.PublicReportByIDCompliance(ctx, public_id, true)
if err != nil {
return nil, nhttp.NewError("get report: %w", err)
}
return res.complianceHydrate(report)
}
func (res *complianceR) Create(ctx context.Context, r *http.Request, n publicreportComplianceForm) (*types.PublicReportCompliance, *nhttp.ErrorWithStatus) {
if n.District.IsUnset() && n.MailerID.IsUnset() {
return nil, nhttp.NewBadRequest("You must provide a district_id or mailer_id")
}
user_agent := r.Header.Get("User-Agent")
err := platform.EnsureClient(ctx, n.ClientID, user_agent)
if err != nil {
return nil, nhttp.NewError("Failed to ensure client: %w", err)
}
2026-04-09 23:38:20 +00:00
setter_report := models.PublicreportReportSetter{
//AddressID: omitnull.From(...),
AddressGid: omit.From(""),
AddressRaw: omit.From(""),
ClientUUID: omitnull.From(n.ClientID),
Created: omit.From(time.Now()),
2026-04-09 23:38:20 +00:00
//H3cell: omitnull.From(latlng.Cell.String()),
LatlngAccuracyType: omit.From(enums.PublicreportAccuracytypeBrowser),
LatlngAccuracyValue: omit.From(float32(0.0)),
//Location: omitnull.From(fmt.Sprintf("ST_GeometryFromText(Point(%s %s))", longitude, latitude)),
Location: omitnull.FromPtr[string](nil),
MapZoom: omit.From(float32(0.0)),
//OrganizationID: omit.From[int32](),
//PublicID: omit.From(),
ReporterEmail: omit.From(""),
ReporterName: omit.From(""),
ReporterPhone: omit.From(""),
2026-04-14 01:21:50 +00:00
ReporterPhoneCanSMS: omit.From(true),
ReportType: omit.From(enums.PublicreportReporttypeCompliance),
Status: omit.From(enums.PublicreportReportstatustypeReported),
2026-04-09 23:38:20 +00:00
}
setter_compliance := models.PublicreportComplianceSetter{
AccessInstructions: omit.From(""),
AvailabilityNotes: omit.From(""),
Comments: omit.From(""),
GateCode: omit.From(""),
HasDog: omitnull.FromPtr[bool](nil),
PermissionType: omit.From(enums.PermissionaccesstypeUnselected),
//ReportID omit.Val[int32]
WantsScheduled: omitnull.FromPtr[bool](nil),
2026-04-09 23:38:20 +00:00
}
var org_id int32
if n.District.IsValue() {
district_str := n.District.MustGet()
var district_id_ptr *int
district_id_ptr, err := res.router.IDFromURI("district.ByIDGet", district_str)
if err != nil || district_id_ptr == nil {
return nil, nhttp.NewBadRequest("parse district ID: %w", err)
}
org_id = int32(*district_id_ptr)
public_id, err := platform.GenerateReportID()
if err != nil {
return nil, nhttp.NewError("generate public ID: %w", err)
}
setter_report.PublicID = omit.From(public_id)
}
if n.MailerID.IsValue() {
public_id := n.MailerID.MustGet()
setter_report.PublicID = omit.From(public_id)
org_id, err = platform.OrganizationIDForComplianceReportRequest(ctx, public_id)
if err != nil {
return nil, nhttp.NewBadRequest("no such mailer")
}
address, err := platform.AddressFromComplianceReportRequestID(ctx, public_id)
if err != nil {
return nil, nhttp.NewError("get address gid: %w", err)
}
setter_report.AddressID = omitnull.FromPtr(address.ID)
setter_report.AddressGid = omit.From(address.GID)
}
report, err := platform.PublicReportComplianceCreate(ctx, setter_report, setter_compliance, org_id)
2026-04-09 23:38:20 +00:00
if err != nil {
return nil, nhttp.NewError("create compliance report: %w", err)
}
// Return a fully-fleshed-out report object, even though it's a bit more expensive
result, err := platform.PublicReportByIDCompliance(ctx, report.PublicID, true)
2026-04-09 23:38:20 +00:00
if err != nil {
return nil, nhttp.NewError("get report after creation: %w", err)
2026-04-09 23:38:20 +00:00
}
return res.complianceHydrate(result)
2026-04-09 23:38:20 +00:00
}
2026-04-13 19:32:22 +00:00
func (res *complianceR) Update(ctx context.Context, r *http.Request, prf publicreportComplianceForm) (*types.PublicReportCompliance, *nhttp.ErrorWithStatus) {
vars := mux.Vars(r)
public_id := vars["id"]
if public_id == "" {
return nil, nhttp.NewBadRequest("You must provide an ID")
}
report_setter := models.PublicreportReportSetter{}
compliance_setter := models.PublicreportComplianceSetter{}
2026-04-13 20:42:03 +00:00
var location *types.Location
if prf.Location.IsValue() {
l := prf.Location.MustGet()
location = &l
if location.Accuracy != nil {
report_setter.LatlngAccuracyValue = omit.From(*location.Accuracy)
2026-04-13 19:32:22 +00:00
}
}
2026-04-13 20:42:03 +00:00
if prf.Reporter.IsValue() {
reporter := prf.Reporter.MustGet()
if reporter.Email != nil {
report_setter.ReporterEmail = omit.From(*reporter.Email)
2026-04-13 19:32:22 +00:00
}
2026-04-13 20:42:03 +00:00
if reporter.Name != nil {
report_setter.ReporterName = omit.From(*reporter.Name)
2026-04-13 19:32:22 +00:00
}
2026-04-13 20:42:03 +00:00
if reporter.Phone != nil {
report_setter.ReporterPhone = omit.From(*reporter.Phone)
2026-04-13 19:32:22 +00:00
}
if reporter.CanSMS != nil {
report_setter.ReporterPhoneCanSMS = omit.FromPtr(reporter.CanSMS)
}
2026-04-13 19:32:22 +00:00
}
2026-04-13 20:42:03 +00:00
var address *types.Address
if prf.Address.IsValue() {
a := prf.Address.MustGet()
address = &a
}
if prf.AccessInstructions.IsValue() {
compliance_setter.AccessInstructions = prf.AccessInstructions
}
if prf.AvailabilityNotes.IsValue() {
compliance_setter.AvailabilityNotes = prf.AvailabilityNotes
}
if prf.Comments.IsValue() {
compliance_setter.Comments = prf.Comments
}
if prf.GateCode.IsValue() {
compliance_setter.GateCode = prf.GateCode
}
if prf.HasDog.IsValue() {
compliance_setter.HasDog = prf.HasDog
}
if prf.PermissionType.IsValue() {
compliance_setter.PermissionType = prf.PermissionType
}
if prf.WantsScheduled.IsValue() {
compliance_setter.WantsScheduled = prf.WantsScheduled
}
log.Debug().
Bool("access_instructions", prf.AccessInstructions.IsValue()).
Bool("access_instructions", prf.AccessInstructions.IsValue()).
Bool("access_instructions", prf.AccessInstructions.IsValue()).
Bool("access_instructions", prf.AccessInstructions.IsValue()).
Msg("updating compliance")
report, err := platform.PublicReportUpdateCompliance(ctx, public_id, &report_setter, &compliance_setter, address, location)
2026-04-13 19:32:22 +00:00
if err != nil {
return nil, nhttp.NewError("platform update report compliance: %w", err)
}
// Return a fully-fleshed-out report object, even though it's a bit more expensive
report, err = platform.PublicReportByIDCompliance(ctx, public_id, true)
if err != nil {
return nil, nhttp.NewError("get report after update: %w", err)
}
return res.complianceHydrate(report)
}
type publicreportComplianceFormSubmit struct {
ClientID uuid.UUID `schema:"client_id" json:"client_id"`
}
func (res *complianceR) Submit(ctx context.Context, r *http.Request, prf publicreportComplianceForm) (*types.PublicReportCompliance, *nhttp.ErrorWithStatus) {
vars := mux.Vars(r)
public_id := vars["id"]
if public_id == "" {
return nil, nhttp.NewBadRequest("You must provide an ID")
}
report, err := platform.PublicReportComplianceSubmit(ctx, public_id, true)
if err != nil {
return nil, nhttp.NewError("submit report: %w", err)
}
return report, nil
}
func (res *complianceR) complianceHydrate(report *types.PublicReportCompliance) (*types.PublicReportCompliance, *nhttp.ErrorWithStatus) {
populateDistrictURI(&report.PublicReport, res.router)
populateReportURI(&report.PublicReport, res.router)
for _, e := range report.Concerns {
e.PopulateURL(res.router.router)
}
2026-04-13 19:32:22 +00:00
return report, nil
}