nidus-sync/db/fieldseeker.go
Eli Ribble 1395e3d3ac Remove old FieldSeeker tables, use v2 generated tables.
This requires a bunch of changes since the types on these tables are
much closer to the underlying types of the Fieldseeker data we are
getting back from the API.

I now need to use proper UUID types everywhere, which means I had to
modify the bob gen config to consistently use google UUID, my UUID
library of choice.

I also had to add the organization_id to all the fieldseeker tables
since we rely on them existing for some of our compound queries.

There were some changes to the API type signatures to get things to
build. I may yet regret those.
2025-12-24 17:58:08 -07:00

1451 lines
60 KiB
Go

package db
import (
"context"
"fmt"
fslayer "github.com/Gleipnir-Technology/arcgis-go/fieldseeker/layer"
"github.com/Gleipnir-Technology/nidus-sync/db/models"
"github.com/aarondl/opt/omit"
"github.com/aarondl/opt/omitnull"
"github.com/gofrs/uuid/v5"
googleuuid "github.com/google/uuid"
"github.com/rs/zerolog/log"
"github.com/stephenafamo/bob"
"github.com/stephenafamo/bob/dialect/psql"
"github.com/stephenafamo/scan"
)
func SaveOrUpdateAerialSpraySession(ctx context.Context, org *models.Organization, fs []*fslayer.AerialSpraySession) (inserts uint, updates uint, err error) {
log.Warn().Msg("Ignoring AerialSpraySession data")
return 0, 0, nil
/*
return doUpdatesViaFunction(ctx, org, fs, "AerialSpraySession", "fieldseeker.insert_aerialspraysession", func(row *fslayer.AerialSpraySession) ([]SqlParam, error) {
return []SqlParam{
//Uint("p_objectid", row.ObjectID),
}, nil
})
*/
}
func SaveOrUpdateAerialSprayLine(ctx context.Context, org *models.Organization, fs []*fslayer.AerialSprayLine) (inserts uint, updates uint, err error) {
log.Warn().Msg("Ignoring AerialSprayLine data")
return 0, 0, nil
/*
return doUpdatesViaFunction(ctx, org, fs, "AerialSprayLine", "fieldseeker.insert_aerialsprayline", func(row *fslayer.AerialSprayLine) ([]SqlParam, error) {
return []SqlParam{
}, nil
})
*/
}
func SaveOrUpdateBarrierSpray(ctx context.Context, org *models.Organization, fs []*fslayer.BarrierSpray) (inserts uint, updates uint, err error) {
log.Warn().Msg("Ignoring BarrierSpray data")
return 0, 0, nil
/*
return doUpdatesViaFunction(ctx, org, fs, "BarrierSpray", "fieldseeker.insert_barrierspray", func(row *fslayer.BarrierSpray) ([]SqlParam, error) {
return []SqlParam{
}, nil
})
*/
}
func SaveOrUpdateBarrierSprayRoute(ctx context.Context, org *models.Organization, fs []*fslayer.BarrierSprayRoute) (inserts uint, updates uint, err error) {
log.Warn().Msg("Ignoring BarrierSprayRoute data")
return 0, 0, nil
/*
return doUpdatesViaFunction(ctx, org, fs, "BarrierSprayRoute", "fieldseeker.insert_barriersprayroute", func(row *fslayer.BarrierSprayRoute) ([]SqlParam, error) {
return []SqlParam{
}, nil
})
*/
}
func SaveOrUpdateContainerRelate(ctx context.Context, org *models.Organization, fs []*fslayer.ContainerRelate) (inserts uint, updates uint, err error) {
return doUpdatesViaFunction(ctx, org, fs, "ContainerRelate", "fieldseeker.insert_containerrelate", func(row *fslayer.ContainerRelate) ([]SqlParam, error) {
gisPoint, err := pointOrNull(row.Geometry)
if err != nil {
return []SqlParam{}, err
}
return []SqlParam{
Uint("p_objectid", row.ObjectID),
Int32("p_organization_id", org.ID),
UUID("p_globalid", row.GlobalID),
String("p_created_user", row.CreatedUser),
Timestamp("p_created_date", row.CreatedDate),
String("p_last_edited_user", row.LastEditedUser),
Timestamp("p_last_edited_date", row.LastEditedDate),
UUID("p_inspsampleid", row.InspsampleID),
UUID("p_mosquitoinspid", row.MosquitoinspID),
UUID("p_treatmentid", row.TreatmentID),
String("p_containertype", row.ContainerType),
Timestamp("p_creationdate", row.CreationDate),
String("p_creator", row.Creator),
Timestamp("p_editdate", row.EditDate),
String("p_editor", row.Editor),
JsonB("p_geometry", row.Geometry),
gisPoint,
}, nil
})
}
func SaveOrUpdateFieldScoutingLog(ctx context.Context, org *models.Organization, fs []*fslayer.FieldScoutingLog) (inserts uint, updates uint, err error) {
return doUpdatesViaFunction(ctx, org, fs, "FieldScoutingLog", "fieldseeker.insert_fieldscoutinglog", func(row *fslayer.FieldScoutingLog) ([]SqlParam, error) {
gisPoint, err := pointOrNull(row.Geometry)
if err != nil {
return []SqlParam{}, err
}
return []SqlParam{
Uint("p_objectid", row.ObjectID),
Int32("p_organization_id", org.ID),
Int16("p_status", row.Status),
UUID("p_globalid", row.GlobalID),
String("p_created_user", row.CreatedUser),
Timestamp("p_created_date", row.CreatedDate),
String("p_last_edited_user", row.LastEditedUser),
Timestamp("p_last_edited_date", row.LastEditedDate),
Timestamp("p_creationdate", row.CreationDate),
String("p_creator", row.Creator),
Timestamp("p_editdate", row.EditDate),
String("p_editor", row.Editor),
JsonB("p_geometry", row.Geometry),
gisPoint,
}, nil
})
return 0, 0, nil
}
func SaveOrUpdateHabitatRelate(ctx context.Context, org *models.Organization, fs []*fslayer.HabitatRelate) (inserts uint, updates uint, err error) {
return doUpdatesViaFunction(ctx, org, fs, "HabitatRelate", "fieldseeker.insert_habitatrelate", func(row *fslayer.HabitatRelate) ([]SqlParam, error) {
gisPoint, err := pointOrNull(row.Geometry)
if err != nil {
return []SqlParam{}, err
}
return []SqlParam{
Uint("p_objectid", row.ObjectID),
Int32("p_organization_id", org.ID),
UUID("p_foreign_id", row.ForeignID),
UUID("p_globalid", row.GlobalID),
String("p_created_user", row.CreatedUser),
Timestamp("p_created_date", row.CreatedDate),
String("p_last_edited_user", row.LastEditedUser),
Timestamp("p_last_edited_date", row.LastEditedDate),
String("p_habitattype", row.HabitatType),
Timestamp("p_creationdate", row.CreationDate),
String("p_creator", row.Creator),
Timestamp("p_editdate", row.EditDate),
String("p_editor", row.Editor),
JsonB("p_geometry", row.Geometry),
gisPoint,
}, nil
})
return 0, 0, nil
}
func SaveOrUpdateInspectionSample(ctx context.Context, org *models.Organization, fs []*fslayer.InspectionSample) (inserts uint, updates uint, err error) {
return doUpdatesViaFunction(ctx, org, fs, "InspectionSample", "fieldseeker.insert_inspectionsample", func(row *fslayer.InspectionSample) ([]SqlParam, error) {
gisPoint, err := pointOrNull(row.Geometry)
if err != nil {
return []SqlParam{}, err
}
return []SqlParam{
Uint("p_objectid", row.ObjectID),
Int32("p_organization_id", org.ID),
UUID("p_insp_id", row.InspID),
String("p_sampleid", row.SampleID),
Int16("p_processed", row.Processed),
String("p_idbytech", row.TechIdentifyingSpeciesInLab),
UUID("p_globalid", row.GlobalID),
String("p_created_user", row.CreatedUser),
Timestamp("p_created_date", row.CreatedDate),
String("p_last_edited_user", row.LastEditedUser),
Timestamp("p_last_edited_date", row.LastEditedDate),
Timestamp("p_creationdate", row.CreationDate),
String("p_creator", row.Creator),
Timestamp("p_editdate", row.EditDate),
String("p_editor", row.Editor),
JsonB("p_geometry", row.Geometry),
gisPoint,
}, nil
})
return 0, 0, nil
}
func SaveOrUpdateInspectionSampleDetail(ctx context.Context, org *models.Organization, fs []*fslayer.InspectionSampleDetail) (inserts uint, updates uint, err error) {
return doUpdatesViaFunction(ctx, org, fs, "InspectionSampleDetail", "fieldseeker.insert_inspectionsampledetail", func(row *fslayer.InspectionSampleDetail) ([]SqlParam, error) {
gisPoint, err := pointOrNull(row.Geometry)
if err != nil {
return []SqlParam{}, err
}
return []SqlParam{
Uint("p_objectid", row.ObjectID),
Int32("p_organization_id", org.ID),
UUID("p_inspsample_id", row.InspsampleID),
String("p_fieldspecies", row.FieldSpecies),
Int16("p_flarvcount", row.FieldLarvaCount),
Int16("p_fpupcount", row.FieldPupaCount),
Int16("p_feggcount", row.FieldEggCount),
String("p_flstages", row.FieldLarvalStages),
String("p_fdomstage", row.FieldDominantStage),
String("p_fadultact", row.FieldAdultActivity),
String("p_labspecies", row.LabSpecies),
Int16("p_llarvcount", row.LabLarvaCount),
Int16("p_lpupcount", row.LabPupaCount),
Int16("p_leggcount", row.LabEggCount),
String("p_ldomstage", row.LabDominantStage),
String("p_comments", row.Comments),
UUID("p_globalid", row.GlobalID),
String("p_created_user", row.CreatedUser),
Timestamp("p_created_date", row.CreatedDate),
String("p_last_edited_user", row.LastEditedUser),
Timestamp("p_last_edited_date", row.LastEditedDate),
Int16("p_processed", row.Processed),
Timestamp("p_creationdate", row.CreationDate),
String("p_creator", row.Creator),
Timestamp("p_editdate", row.EditDate),
String("p_editor", row.Editor),
JsonB("p_geometry", row.Geometry),
gisPoint,
}, nil
})
return 0, 0, nil
}
func SaveOrUpdateLandingCount(ctx context.Context, org *models.Organization, fs []*fslayer.LandingCount) (inserts uint, updates uint, err error) {
log.Warn().Msg("Ignoring LandingCount data")
return 0, 0, nil
/*
return doUpdatesViaFunction(ctx, org, fs, "LandingCount", "fieldseeker.insert_landingcount", func(row *fslayer.LandingCount) ([]SqlParam, error) {
return []SqlParam{
Uint("p_objectid", row.ObjectID),
}, nil
})
*/
}
func SaveOrUpdateLandingCountLocation(ctx context.Context, org *models.Organization, fs []*fslayer.LandingCountLocation) (inserts uint, updates uint, err error) {
log.Warn().Msg("Ignoring LandingCountLocation data")
return 0, 0, nil
/*
return doUpdatesViaFunction(ctx, org, fs, "LandingCountLocation", "fieldseeker.insert_landingcountlocation", func(row *fslayer.LandingCountLocation) ([]SqlParam, error) {
return []SqlParam{
Uint("p_objectid", row.ObjectID),
}, nil
})
*/
}
func SaveOrUpdateLineLocation(ctx context.Context, org *models.Organization, fs []*fslayer.LineLocation) (inserts uint, updates uint, err error) {
return doUpdatesViaFunction(ctx, org, fs, "LineLocation", "fieldseeker.insert_linelocation", func(row *fslayer.LineLocation) ([]SqlParam, error) {
gisPoint, err := lineOrNull(row.Geometry)
if err != nil {
return []SqlParam{}, err
}
return []SqlParam{
Uint("p_objectid", row.ObjectID),
Int32("p_organization_id", org.ID),
String("p_name", row.Name),
String("p_zone", row.Zone),
String("p_habitat", row.Habitat),
String("p_priority", row.Priority),
String("p_usetype", row.UseType),
Int16("p_active", row.Active),
String("p_description", row.Description),
String("p_accessdesc", row.AccessDescription),
String("p_comments", row.Comments),
String("p_symbology", row.Symbology),
String("p_externalid", row.ExternalID),
Float64("p_acres", row.Acres),
Timestamp("p_nextactiondatescheduled", row.NextScheduledAction),
Int16("p_larvinspectinterval", row.LarvalInspectionInterval),
Float64("p_length_ft", row.Length),
Float64("p_width_ft", row.Width),
String("p_zone2", row.Zone2),
Int32("p_locationnumber", row.Locationnumber),
UUID("p_globalid", row.GlobalID),
String("p_created_user", row.CreatedUser),
Timestamp("p_created_date", row.CreatedDate),
String("p_last_edited_user", row.LastEditedUser),
Timestamp("p_last_edited_date", row.LastEditedDate),
Timestamp("p_lastinspectdate", row.LastInspectionDate),
String("p_lastinspectbreeding", row.LastInspectionBreeding),
Float64("p_lastinspectavglarvae", row.LastInspectionAverageLarvae),
Float64("p_lastinspectavgpupae", row.LastInspectionAveragePupae),
String("p_lastinspectlstages", row.LastInspectionLarvalStages),
String("p_lastinspectactiontaken", row.LastInspectionAction),
String("p_lastinspectfieldspecies", row.LastInspectionFieldSpecies),
Timestamp("p_lasttreatdate", row.LastTreatmentDate),
String("p_lasttreatproduct", row.LastTreatmentProduct),
Float64("p_lasttreatqty", row.LastTreatmentQuantity),
String("p_lasttreatqtyunit", row.LastTreatmentQuantityUnit),
Float64("p_hectares", row.Hectares),
String("p_lastinspectactivity", row.LastInspectionActivity),
String("p_lasttreatactivity", row.LastTreatmentActivity),
Float64("p_length_meters", row.LengthMeters),
Float64("p_width_meters", row.WidthMeters),
String("p_lastinspectconditions", row.LastInspectionConditions),
String("p_waterorigin", row.WaterOrigin),
Timestamp("p_creationdate", row.CreationDate),
String("p_creator", row.Creator),
Timestamp("p_editdate", row.EditDate),
String("p_editor", row.Editor),
String("p_jurisdiction", row.Jurisdiction),
Float64("p_shape__length", row.ShapeLength),
JsonB("p_geometry", row.Geometry),
gisPoint,
}, nil
})
return 0, 0, nil
}
func SaveOrUpdateLocationTracking(ctx context.Context, org *models.Organization, fs []*fslayer.LocationTracking) (inserts uint, updates uint, err error) {
return doUpdatesViaFunction(ctx, org, fs, "LocationTracking", "fieldseeker.insert_locationtracking", func(row *fslayer.LocationTracking) ([]SqlParam, error) {
gisPoint, err := pointOrNull(row.Geometry)
if err != nil {
return []SqlParam{}, err
}
return []SqlParam{
Uint("p_objectid", row.ObjectID),
Int32("p_organization_id", org.ID),
Float64("p_accuracy", row.Accuracym),
String("p_created_user", row.CreatedUser),
Timestamp("p_created_date", row.CreatedDate),
String("p_last_edited_user", row.LastEditedUser),
Timestamp("p_last_edited_date", row.LastEditedDate),
UUID("p_globalid", row.GlobalID),
String("p_fieldtech", row.FieldTech),
Timestamp("p_creationdate", row.CreationDate),
String("p_creator", row.Creator),
Timestamp("p_editdate", row.EditDate),
String("p_editor", row.Editor),
JsonB("p_geometry", row.Geometry),
gisPoint,
}, nil
})
return 0, 0, nil
}
func SaveOrUpdateMosquitoInspection(ctx context.Context, org *models.Organization, fs []*fslayer.MosquitoInspection) (inserts uint, updates uint, err error) {
return doUpdatesViaFunction(ctx, org, fs, "MosquitoInspection", "fieldseeker.insert_mosquitoinspection", func(row *fslayer.MosquitoInspection) ([]SqlParam, error) {
gisPoint, err := pointOrNull(row.Geometry)
if err != nil {
return []SqlParam{}, err
}
return []SqlParam{
Uint("p_objectid", row.ObjectID),
Int32("p_organization_id", org.ID),
Int16("p_numdips", row.Dips),
String("p_activity", row.Activity),
String("p_breeding", row.Breeding),
Int16("p_totlarvae", row.TotalLarvae),
Int16("p_totpupae", row.TotalPupae),
Int16("p_eggs", row.Eggs),
Int16("p_posdips", row.PositiveDips),
String("p_adultact", row.AdultActivity),
String("p_lstages", row.LarvalStages),
String("p_domstage", row.DominantStage),
String("p_actiontaken", row.Action),
String("p_comments", row.Comments),
Float64("p_avetemp", row.AverageTemperature),
Float64("p_windspeed", row.WindSpeed),
Float64("p_raingauge", row.RainGauge),
Timestamp("p_startdatetime", row.Start),
Timestamp("p_enddatetime", row.Finish),
String("p_winddir", row.WindDirection),
Float64("p_avglarvae", row.AverageLarvae),
Float64("p_avgpupae", row.AveragePupae),
Int16("p_reviewed", row.Reviewed),
String("p_reviewedby", row.ReviewedBy),
Timestamp("p_revieweddate", row.ReviewedDate),
String("p_locationname", row.LocationName),
String("p_zone", row.Zone),
Int16("p_recordstatus", row.RecordStatus),
String("p_zone2", row.Zone2),
Int16("p_personalcontact", row.PersonalContact),
Int16("p_tirecount", row.TireCount),
Int16("p_cbcount", row.CatchBasinCount),
Int16("p_containercount", row.ContainerCount),
String("p_fieldspecies", row.FieldSpecies),
UUID("p_globalid", row.GlobalID),
String("p_created_user", row.CreatedUser),
Timestamp("p_created_date", row.CreatedDate),
String("p_last_edited_user", row.LastEditedUser),
Timestamp("p_last_edited_date", row.LastEditedDate),
UUID("p_linelocid", row.LinelocID),
UUID("p_pointlocid", row.PointlocID),
UUID("p_polygonlocid", row.PolygonlocID),
UUID("p_srid", row.SrID),
String("p_fieldtech", row.FieldTech),
Int16("p_larvaepresent", row.LarvaePresent),
Int16("p_pupaepresent", row.PupaePresent),
UUID("p_sdid", row.StormDrainID),
String("p_sitecond", row.Conditions),
Int16("p_positivecontainercount", row.PositiveContainerCount),
Timestamp("p_creationdate", row.CreationDate),
String("p_creator", row.Creator),
Timestamp("p_editdate", row.EditDate),
String("p_editor", row.Editor),
String("p_jurisdiction", row.Jurisdiction),
Int16("p_visualmonitoring", row.VisualMonitoring),
String("p_vmcomments", row.VmComments),
String("p_adminaction", row.AdminAction),
UUID("p_ptaid", row.PtaID),
JsonB("p_geometry", row.Geometry),
gisPoint,
}, nil
})
}
func SaveOrUpdateOfflineMapAreas(ctx context.Context, org *models.Organization, fs []*fslayer.OfflineMapAreas) (inserts uint, updates uint, err error) {
log.Warn().Msg("Ignoring OfflineMapAreas data")
return 0, 0, nil
/*
return doUpdatesViaFunction(ctx, org, fs, "OfflineMapAreas", "fieldseeker.insert_offlinemapareas", func(row *fslayer.OfflineMapAreas) ([]SqlParam, error) {
return []SqlParam{
Uint("p_objectid", row.ObjectID),
}, nil
})
*/
}
func SaveOrUpdateProposedTreatmentArea(ctx context.Context, org *models.Organization, fs []*fslayer.ProposedTreatmentArea) (inserts uint, updates uint, err error) {
return doUpdatesViaFunction(ctx, org, fs, "ProposedTreatmentArea", "fieldseeker.insert_proposedtreatmentarea", func(row *fslayer.ProposedTreatmentArea) ([]SqlParam, error) {
gisPoint, err := polygonOrNull(row.Geometry)
if err != nil {
return []SqlParam{}, err
}
// At this point we've got data that's bad and can't actually be inserted in the database
// so let's just always make the geo null
gisPoint = NullParam{"p_geospatial"}
return []SqlParam{
Uint("p_objectid", row.ObjectID),
Int32("p_organization_id", org.ID),
String("p_method", row.Method),
String("p_comments", row.Comments),
String("p_zone", row.Zone),
Int16("p_reviewed", row.Reviewed),
String("p_reviewedby", row.ReviewedBy),
Timestamp("p_revieweddate", row.ReviewedDate),
String("p_zone2", row.Zone2),
Timestamp("p_completeddate", row.CompletedDate),
String("p_completedby", row.CompletedBy),
Int16("p_completed", row.Completed),
Int16("p_issprayroute", row.IsSprayRoute),
String("p_name", row.Name),
Float64("p_acres", row.Acres),
UUID("p_globalid", row.GlobalID),
Int16("p_exported", row.Exported),
String("p_targetproduct", row.TargetProduct),
Float64("p_targetapprate", row.TargetAppRate),
Float64("p_hectares", row.Hectares),
String("p_lasttreatactivity", row.LastTreatmentActivity),
Timestamp("p_lasttreatdate", row.LastTreatmentDate),
String("p_lasttreatproduct", row.LastTreatmentProduct),
Float64("p_lasttreatqty", row.LastTreatmentQuantity),
String("p_lasttreatqtyunit", row.LastTreatmentQuantityUnit),
String("p_priority", row.Priority),
Timestamp("p_duedate", row.DueDate),
Timestamp("p_creationdate", row.CreationDate),
String("p_creator", row.Creator),
Timestamp("p_editdate", row.EditDate),
String("p_editor", row.Editor),
String("p_targetspecies", row.TargetSpecies),
Float64("p_shape__area", row.ShapeArea),
Float64("p_shape__length", row.ShapeLength),
JsonB("p_geometry", row.Geometry),
gisPoint,
}, nil
})
}
func SaveOrUpdatePointLocation(ctx context.Context, org *models.Organization, fs []*fslayer.PointLocation) (inserts uint, updates uint, err error) {
return doUpdatesViaFunction(ctx, org, fs, "PointLocation", "fieldseeker.insert_pointlocation", func(row *fslayer.PointLocation) ([]SqlParam, error) {
gisPoint, err := pointOrNull(row.Geometry)
if err != nil {
return []SqlParam{}, err
}
return []SqlParam{
Uint("p_objectid", row.ObjectID),
Int32("p_organization_id", org.ID),
String("p_name", row.Name),
String("p_zone", row.Zone),
String("p_habitat", row.Habitat),
String("p_priority", row.Priority),
String("p_usetype", row.UseType),
Int16("p_active", row.Active),
String("p_description", row.Description),
String("p_accessdesc", row.AccessDescription),
String("p_comments", row.Comments),
String("p_symbology", row.Symbology),
String("p_externalid", row.ExternalID),
Timestamp("p_nextactiondatescheduled", row.NextScheduledAction),
Int16("p_larvinspectinterval", row.LarvalInspectionInterval),
String("p_zone2", row.Zone2),
Int32("p_locationnumber", row.Locationnumber),
UUID("p_globalid", row.GlobalID),
String("p_stype", row.SourceType),
Timestamp("p_lastinspectdate", row.LastInspectionDate),
String("p_lastinspectbreeding", row.LastInspectionBreeding),
Float64("p_lastinspectavglarvae", row.LastInspectionAverageLarvae),
Float64("p_lastinspectavgpupae", row.LastInspectionAveragePupae),
String("p_lastinspectlstages", row.LastInspectionLarvalStages),
String("p_lastinspectactiontaken", row.LastInspectionAction),
String("p_lastinspectfieldspecies", row.LastInspectionFieldSpecies),
Timestamp("p_lasttreatdate", row.LastTreatmentDate),
String("p_lasttreatproduct", row.LastTreatmentProduct),
Float64("p_lasttreatqty", row.LastTreatmentQuantity),
String("p_lasttreatqtyunit", row.LastTreatmentQuantityUnit),
String("p_lastinspectactivity", row.LastInspectionActivity),
String("p_lasttreatactivity", row.LastTreatmentActivity),
String("p_lastinspectconditions", row.LastInspectionConditions),
String("p_waterorigin", row.WaterOrigin),
Float64("p_x", row.X),
Float64("p_y", row.Y),
String("p_assignedtech", row.AssignedTech),
Timestamp("p_creationdate", row.CreationDate),
String("p_creator", row.Creator),
Timestamp("p_editdate", row.EditDate),
String("p_editor", row.Editor),
String("p_jurisdiction", row.Jurisdiction),
String("p_deactivate_reason", row.ReasonForDeactivation),
Int32("p_scalarpriority", row.ScalarPriority),
String("p_sourcestatus", row.SourceStatus),
JsonB("p_geometry", row.Geometry),
gisPoint,
}, nil
})
return 0, 0, nil
}
func SaveOrUpdatePolygonLocation(ctx context.Context, org *models.Organization, fs []*fslayer.PolygonLocation) (inserts uint, updates uint, err error) {
return doUpdatesViaFunction(ctx, org, fs, "PolygonLocation", "fieldseeker.insert_polygonlocation", func(row *fslayer.PolygonLocation) ([]SqlParam, error) {
gisPoint, err := polygonOrNull(row.Geometry)
if err != nil {
return []SqlParam{}, err
}
// At this point we've got data that's bad and can't actually be inserted in the database
// so let's just always make the geo null
gisPoint = NullParam{"p_geospatial"}
return []SqlParam{
Uint("p_objectid", row.ObjectID),
Int32("p_organization_id", org.ID),
String("p_name", row.Name),
String("p_zone", row.Zone),
String("p_habitat", row.Habitat),
String("p_priority", row.Priority),
String("p_usetype", row.UseType),
Int16("p_active", row.Active),
String("p_description", row.Description),
String("p_accessdesc", row.AccessDescription),
String("p_comments", row.Comments),
String("p_symbology", row.Symbology),
String("p_externalid", row.ExternalID),
Float64("p_acres", row.Acres),
Timestamp("p_nextactiondatescheduled", row.NextScheduledAction),
Int16("p_larvinspectinterval", row.LarvalInspectionInterval),
String("p_zone2", row.Zone2),
Int32("p_locationnumber", row.Locationnumber),
UUID("p_globalid", row.GlobalID),
Timestamp("p_lastinspectdate", row.LastInspectionDate),
String("p_lastinspectbreeding", row.LastInspectionBreeding),
Float64("p_lastinspectavglarvae", row.LastInspectionAverageLarvae),
Float64("p_lastinspectavgpupae", row.LastInspectionAveragePupae),
String("p_lastinspectlstages", row.LastInspectionLarvalStages),
String("p_lastinspectactiontaken", row.LastInspectionAction),
String("p_lastinspectfieldspecies", row.LastInspectionFieldSpecies),
Timestamp("p_lasttreatdate", row.LastTreatmentDate),
String("p_lasttreatproduct", row.LastTreatmentProduct),
Float64("p_lasttreatqty", row.LastTreatmentQuantity),
String("p_lasttreatqtyunit", row.LastTreatmentQuantityUnit),
Float64("p_hectares", row.Hectares),
String("p_lastinspectactivity", row.LastInspectionActivity),
String("p_lasttreatactivity", row.LastTreatmentActivity),
String("p_lastinspectconditions", row.LastInspectionConditions),
String("p_waterorigin", row.WaterOrigin),
String("p_filter", row.Filter),
Timestamp("p_creationdate", row.CreationDate),
String("p_creator", row.Creator),
Timestamp("p_editdate", row.EditDate),
String("p_editor", row.Editor),
String("p_jurisdiction", row.Jurisdiction),
Float64("p_shape__area", row.ShapeArea),
Float64("p_shape__length", row.ShapeLength),
JsonB("p_geometry", row.Geometry),
gisPoint,
}, nil
})
return 0, 0, nil
}
func SaveOrUpdatePoolDetail(ctx context.Context, org *models.Organization, fs []*fslayer.PoolDetail) (inserts uint, updates uint, err error) {
return doUpdatesViaFunction(ctx, org, fs, "PoolDetail", "fieldseeker.insert_pooldetail", func(row *fslayer.PoolDetail) ([]SqlParam, error) {
gisPoint, err := pointOrNull(row.Geometry)
if err != nil {
return []SqlParam{}, err
}
return []SqlParam{
Uint("p_objectid", row.ObjectID),
Int32("p_organization_id", org.ID),
UUID("p_trapdata_id", row.TrapDataID),
UUID("p_pool_id", row.PoolID),
String("p_species", row.Species),
Int16("p_females", row.Females),
UUID("p_globalid", row.GlobalID),
String("p_created_user", row.CreatedUser),
Timestamp("p_created_date", row.CreatedDate),
String("p_last_edited_user", row.LastEditedUser),
Timestamp("p_last_edited_date", row.LastEditedDate),
Timestamp("p_creationdate", row.CreationDate),
String("p_creator", row.Creator),
Timestamp("p_editdate", row.EditDate),
String("p_editor", row.Editor),
JsonB("p_geometry", row.Geometry),
gisPoint,
}, nil
})
return 0, 0, nil
}
func SaveOrUpdatePool(ctx context.Context, org *models.Organization, fs []*fslayer.Pool) (inserts uint, updates uint, err error) {
return doUpdatesViaFunction(ctx, org, fs, "Pool", "fieldseeker.insert_pool", func(row *fslayer.Pool) ([]SqlParam, error) {
gisPoint, err := pointOrNull(row.Geometry)
if err != nil {
return []SqlParam{}, err
}
return []SqlParam{
Uint("p_objectid", row.ObjectID),
Int32("p_organization_id", org.ID),
UUID("p_trapdata_id", row.TrapDataID),
Timestamp("p_datesent", row.DateSent),
String("p_survtech", row.SurveyTech),
Timestamp("p_datetested", row.DateTested),
String("p_testtech", row.TestTech),
String("p_comments", row.Comments),
String("p_sampleid", row.SampleID),
Int16("p_processed", row.Processed),
UUID("p_lab_id", row.LabID),
String("p_testmethod", row.TestMethods),
String("p_diseasetested", row.DiseasesTested),
String("p_diseasepos", row.DiseasesPositive),
UUID("p_globalid", row.GlobalID),
String("p_created_user", row.CreatedUser),
Timestamp("p_created_date", row.CreatedDate),
String("p_last_edited_user", row.LastEditedUser),
Timestamp("p_last_edited_date", row.LastEditedDate),
String("p_lab", row.Lab),
Int16("p_poolyear", row.PoolYear),
Int16("p_gatewaysync", row.GatewaySync),
String("p_vectorsurvcollectionid", row.VectorsurvcollectionID),
String("p_vectorsurvpoolid", row.VectorsurvpoolID),
String("p_vectorsurvtrapdataid", row.VectorsurvtrapdataID),
Timestamp("p_creationdate", row.CreationDate),
String("p_creator", row.Creator),
Timestamp("p_editdate", row.EditDate),
String("p_editor", row.Editor),
JsonB("p_geometry", row.Geometry),
gisPoint,
}, nil
})
return 0, 0, nil
}
func SaveOrUpdatePoolBuffer(ctx context.Context, org *models.Organization, fs []*fslayer.PoolBuffer) (inserts uint, updates uint, err error) {
log.Warn().Msg("Ignoring PoolBuffer data")
return 0, 0, nil
/*
return doUpdatesViaFunction(ctx, org, fs, "PoolBuffer", "fieldseeker.insert_poolbuffer", func(row *fslayer.PoolBuffer) ([]SqlParam, error) {
return []SqlParam{
Uint("p_objectid", row.ObjectID),
}, nil
})
*/
}
func SaveOrUpdateQALarvCount(ctx context.Context, org *models.Organization, fs []*fslayer.QALarvCount) (inserts uint, updates uint, err error) {
log.Warn().Msg("Ignoring QALarvCount data")
return 0, 0, nil
/*
return doUpdatesViaFunction(ctx, org, fs, "QALarvCount", "fieldseeker.insert_qalarvcount", func(row *fslayer.QALarvCount) ([]SqlParam, error) {
return []SqlParam{
Uint("p_objectid", row.ObjectID),
}, nil
})
*/
}
func SaveOrUpdateQAMosquitoInspection(ctx context.Context, org *models.Organization, fs []*fslayer.QAMosquitoInspection) (inserts uint, updates uint, err error) {
return doUpdatesViaFunction(ctx, org, fs, "QAMosquitoInspection", "fieldseeker.insert_qamosquitoinspection", func(row *fslayer.QAMosquitoInspection) ([]SqlParam, error) {
gisPoint, err := pointOrNull(row.Geometry)
if err != nil {
return []SqlParam{}, err
}
return []SqlParam{
Uint("p_objectid", row.ObjectID),
Int32("p_organization_id", org.ID),
Int16("p_posdips", row.PositiveDips),
String("p_actiontaken", row.Action),
String("p_comments", row.Comments),
Float64("p_avetemp", row.AverageTemperature),
Float64("p_windspeed", row.WindSpeed),
Float64("p_raingauge", row.RainGauge),
UUID("p_globalid", row.GlobalID),
Timestamp("p_startdatetime", row.Start),
Timestamp("p_enddatetime", row.Finish),
String("p_winddir", row.WindDirection),
Int16("p_reviewed", row.Reviewed),
String("p_reviewedby", row.Reviewedby),
Timestamp("p_revieweddate", row.Revieweddate),
String("p_locationname", row.Locationname),
String("p_zone", row.Zone),
Int16("p_recordstatus", row.Recordstatus),
String("p_zone2", row.Zone2),
Int16("p_lr", row.LandingRate),
Int16("p_negdips", row.NegativeDips),
Float64("p_totalacres", row.TotalAcres),
Float64("p_acresbreeding", row.AcresBreeding),
Int16("p_fish", row.FishPresent),
String("p_sitetype", row.SiteType),
String("p_breedingpotential", row.BreedingPotential),
Int16("p_movingwater", row.MovingWater),
Int16("p_nowaterever", row.NoEvidenceOfWaterEver),
String("p_mosquitohabitat", row.MosquitoHabitatIndicators),
Int16("p_habvalue1", row.HabitatValue),
Int16("p_habvalue1percent", row.Habvalue1percent),
Int16("p_habvalue2", row.HabitatValue2),
Int16("p_habvalue2percent", row.Habvalue2percent),
Int16("p_potential", row.Potential),
Int16("p_larvaepresent", row.LarvaePresent),
Int16("p_larvaeinsidetreatedarea", row.LarvaeInsideTreatedArea),
Int16("p_larvaeoutsidetreatedarea", row.LarvaeOutsideTreatedArea),
String("p_larvaereason", row.ReasonLarvaePresent),
String("p_aquaticorganisms", row.AquaticOrganisms),
String("p_vegetation", row.Vegetation),
String("p_sourcereduction", row.SourceReduction),
Int16("p_waterpresent", row.WaterPresent),
String("p_watermovement1", row.WaterMovement),
Int16("p_watermovement1percent", row.Watermovement1percent),
String("p_watermovement2", row.WaterMovement2),
Int16("p_watermovement2percent", row.Watermovement2percent),
String("p_soilconditions", row.SoilConditions),
String("p_waterduration", row.HowLongWaterPresent),
String("p_watersource", row.WaterSource),
String("p_waterconditions", row.WaterConditions),
Int16("p_adultactivity", row.AdultActivity),
UUID("p_linelocid", row.LinelocID),
UUID("p_pointlocid", row.PointlocID),
UUID("p_polygonlocid", row.PolygonlocID),
String("p_created_user", row.CreatedUser),
Timestamp("p_created_date", row.CreatedDate),
String("p_last_edited_user", row.LastEditedUser),
Timestamp("p_last_edited_date", row.LastEditedDate),
String("p_fieldtech", row.FieldTech),
Timestamp("p_creationdate", row.CreationDate),
String("p_creator", row.Creator),
Timestamp("p_editdate", row.EditDate),
String("p_editor", row.Editor),
JsonB("p_geometry", row.Geometry),
gisPoint,
}, nil
})
return 0, 0, nil
}
func SaveOrUpdateQAProductObservation(ctx context.Context, org *models.Organization, fs []*fslayer.QAProductObservation) (inserts uint, updates uint, err error) {
log.Warn().Msg("Ignoring QAProductObservation data")
return 0, 0, nil
/*
return doUpdatesViaFunction(ctx, org, fs, "QAProductObservation", "fieldseeker.insert_qaproductobservation", func(row *fslayer.QAProductObservation) ([]SqlParam, error) {
return []SqlParam{
Uint("p_objectid", row.ObjectID),
}, nil
})
*/
}
func SaveOrUpdateRestrictedArea(ctx context.Context, org *models.Organization, fs []*fslayer.RestrictedArea) (inserts uint, updates uint, err error) {
log.Warn().Msg("Ignoring RestrictedArea data")
return 0, 0, nil
/*
return doUpdatesViaFunction(ctx, org, fs, "RestrictedArea", "fieldseeker.insert_restrictedarea", func(row *fslayer.RestrictedArea) ([]SqlParam, error) {
return []SqlParam{
Uint("p_objectid", row.ObjectID),
}, nil
})
*/
}
func SaveOrUpdateRodentInspection(ctx context.Context, org *models.Organization, fs []*fslayer.RodentInspection) (inserts uint, updates uint, err error) {
log.Warn().Msg("Ignoring RodentInspection data")
return 0, 0, nil
/*
return doUpdatesViaFunction(ctx, org, fs, "RodentInspection", "fieldseeker.insert_rodentinspection", func(row *fslayer.RodentInspection) ([]SqlParam, error) {
return []SqlParam{
Uint("p_objectid", row.ObjectID),
}, nil
})
*/
}
func SaveOrUpdateRodentLocation(ctx context.Context, org *models.Organization, fs []*fslayer.RodentLocation) (inserts uint, updates uint, err error) {
return doUpdatesViaFunction(ctx, org, fs, "RodentLocation", "fieldseeker.insert_rodentlocation", func(row *fslayer.RodentLocation) ([]SqlParam, error) {
gisPoint, err := pointOrNull(row.Geometry)
if err != nil {
return []SqlParam{}, err
}
return []SqlParam{
Uint("p_objectid", row.ObjectID),
Int32("p_organization_id", org.ID),
String("p_locationname", row.LocationName),
String("p_zone", row.Zone),
String("p_zone2", row.Zone2),
String("p_habitat", row.Habitat),
String("p_priority", row.Priority),
String("p_usetype", row.Usetype),
Int16("p_active", row.Active),
String("p_description", row.Description),
String("p_accessdesc", row.Accessdesc),
String("p_comments", row.Comments),
String("p_symbology", row.Symbology),
String("p_externalid", row.ExternalID),
Timestamp("p_nextactiondatescheduled", row.Nextactiondatescheduled),
Int32("p_locationnumber", row.Locationnumber),
Timestamp("p_lastinspectdate", row.LastInspectionDate),
String("p_lastinspectspecies", row.LastInspectionSpecies),
String("p_lastinspectaction", row.LastInspectionAction),
String("p_lastinspectconditions", row.LastInspectionConditions),
String("p_lastinspectrodentevidence", row.LastInspectionRodentEvidence),
UUID("p_globalid", row.GlobalID),
String("p_created_user", row.CreatedUser),
Timestamp("p_created_date", row.CreatedDate),
String("p_last_edited_user", row.LastEditedUser),
Timestamp("p_last_edited_date", row.LastEditedDate),
Timestamp("p_creationdate", row.CreationDate),
String("p_creator", row.Creator),
Timestamp("p_editdate", row.EditDate),
String("p_editor", row.Editor),
String("p_jurisdiction", row.Jurisdiction),
JsonB("p_geometry", row.Geometry),
gisPoint,
}, nil
})
}
func SaveOrUpdateSampleCollection(ctx context.Context, org *models.Organization, fs []*fslayer.SampleCollection) (inserts uint, updates uint, err error) {
return doUpdatesViaFunction(ctx, org, fs, "SampleCollection", "fieldseeker.insert_samplecollection", func(row *fslayer.SampleCollection) ([]SqlParam, error) {
gisPoint, err := pointOrNull(row.Geometry)
if err != nil {
return []SqlParam{}, err
}
return []SqlParam{
Uint("p_objectid", row.ObjectID),
Int32("p_organization_id", org.ID),
UUID("p_loc_id", row.LocID),
Timestamp("p_startdatetime", row.Start),
Timestamp("p_enddatetime", row.Finish),
String("p_sitecond", row.Conditions),
String("p_sampleid", row.SampleID),
String("p_survtech", row.SurveillanceTechnician),
Timestamp("p_datesent", row.Sent),
Timestamp("p_datetested", row.Tested),
String("p_testtech", row.TestTechnician),
String("p_comments", row.Comments),
Int16("p_processed", row.Processed),
String("p_sampletype", row.SampleType),
String("p_samplecond", row.SampleCondition),
String("p_species", row.Species),
String("p_sex", row.Sex),
Float64("p_avetemp", row.AverageTemperature),
Float64("p_windspeed", row.WindSpeed),
String("p_winddir", row.WindDirection),
Float64("p_raingauge", row.RainGauge),
String("p_activity", row.Activity),
String("p_testmethod", row.TestMethod),
String("p_diseasetested", row.DiseaseTested),
String("p_diseasepos", row.DiseasePositive),
Int16("p_reviewed", row.Reviewed),
String("p_reviewedby", row.ReviewedBy),
Timestamp("p_revieweddate", row.ReviewedDate),
String("p_locationname", row.LocationName),
String("p_zone", row.Zone),
Int16("p_recordstatus", row.RecordStatus),
String("p_zone2", row.Zone2),
UUID("p_globalid", row.GlobalID),
String("p_created_user", row.CreatedUser),
Timestamp("p_created_date", row.CreatedDate),
String("p_last_edited_user", row.LastEditedUser),
Timestamp("p_last_edited_date", row.LastEditedDate),
String("p_lab", row.Lab),
String("p_fieldtech", row.FieldTech),
UUID("p_flockid", row.FlockID),
Int16("p_samplecount", row.SampleCount),
UUID("p_chickenid", row.ChickenID),
Int16("p_gatewaysync", row.GatewaySync),
Timestamp("p_creationdate", row.CreationDate),
String("p_creator", row.Creator),
Timestamp("p_editdate", row.EditDate),
String("p_editor", row.Editor),
JsonB("p_geometry", row.Geometry),
gisPoint,
}, nil
})
return 0, 0, nil
}
func SaveOrUpdateSampleLocation(ctx context.Context, org *models.Organization, fs []*fslayer.SampleLocation) (inserts uint, updates uint, err error) {
return doUpdatesViaFunction(ctx, org, fs, "SampleLocation", "fieldseeker.insert_samplelocation", func(row *fslayer.SampleLocation) ([]SqlParam, error) {
gisPoint, err := pointOrNull(row.Geometry)
if err != nil {
return []SqlParam{}, err
}
return []SqlParam{
Uint("p_objectid", row.ObjectID),
Int32("p_organization_id", org.ID),
String("p_name", row.Name),
String("p_zone", row.Zone),
String("p_habitat", row.Habitat),
String("p_priority", row.Priority),
String("p_usetype", row.UseType),
Int16("p_active", row.Active),
String("p_description", row.Description),
String("p_accessdesc", row.AccessDescription),
String("p_comments", row.Comments),
String("p_externalid", row.ExternalID),
Timestamp("p_nextactiondatescheduled", row.NextScheduledAction),
String("p_zone2", row.Zone2),
Int32("p_locationnumber", row.Locationnumber),
UUID("p_globalid", row.GlobalID),
String("p_created_user", row.CreatedUser),
Timestamp("p_created_date", row.CreatedDate),
String("p_last_edited_user", row.LastEditedUser),
Timestamp("p_last_edited_date", row.LastEditedDate),
Int16("p_gatewaysync", row.GatewaySync),
Timestamp("p_creationdate", row.CreationDate),
String("p_creator", row.Creator),
Timestamp("p_editdate", row.EditDate),
String("p_editor", row.Editor),
JsonB("p_geometry", row.Geometry),
gisPoint,
}, nil
})
return 0, 0, nil
}
func SaveOrUpdateServiceRequest(ctx context.Context, org *models.Organization, fs []*fslayer.ServiceRequest) (inserts uint, updates uint, err error) {
return doUpdatesViaFunction(ctx, org, fs, "ServiceRequest", "fieldseeker.insert_servicerequest", func(row *fslayer.ServiceRequest) ([]SqlParam, error) {
gisPoint, err := pointOrNull(row.Geometry)
if err != nil {
return []SqlParam{}, err
}
return []SqlParam{
Uint("p_objectid", row.ObjectID),
Int32("p_organization_id", org.ID),
Timestamp("p_recdatetime", row.Received),
String("p_source", row.Source),
String("p_entrytech", row.EnteredBy),
String("p_priority", row.Priority),
String("p_supervisor", row.Supervisor),
String("p_assignedtech", row.AssignedTo),
String("p_status", row.Status),
Int16("p_clranon", row.AnonymousCaller),
String("p_clrfname", row.CallerName),
String("p_clrphone1", row.CallerPhone),
String("p_clrphone2", row.CallerAlternatePhone),
String("p_clremail", row.CallerEmail),
String("p_clrcompany", row.CallerCompany),
String("p_clraddr1", row.CallerAddress),
String("p_clraddr2", row.CallerAddress2),
String("p_clrcity", row.CallerCity),
String("p_clrstate", row.CallerState),
String("p_clrzip", row.CallerZip),
String("p_clrother", row.CallerOther),
String("p_clrcontpref", row.CallerContactPreference),
String("p_reqcompany", row.RequestCompany),
String("p_reqaddr1", row.RequestAddress),
String("p_reqaddr2", row.RequestAddress2),
String("p_reqcity", row.RequestCity),
String("p_reqstate", row.RequestState),
String("p_reqzip", row.RequestZip),
String("p_reqcrossst", row.RequestCrossStreet),
String("p_reqsubdiv", row.RequestSubdivision),
String("p_reqmapgrid", row.RequestMapGrID),
Int16("p_reqpermission", row.PermissionToEnter),
String("p_reqtarget", row.RequestTarget),
String("p_reqdescr", row.RequestDescription),
String("p_reqnotesfortech", row.NotesForFieldTechnician),
String("p_reqnotesforcust", row.NotesForCustomer),
String("p_reqfldnotes", row.RequestFieldNotes),
String("p_reqprogramactions", row.RequestProgramActions),
Timestamp("p_datetimeclosed", row.Closed),
String("p_techclosed", row.ClosedBy),
Int32("p_sr_number", row.Sr),
Int16("p_reviewed", row.Reviewed),
String("p_reviewedby", row.ReviewedBy),
Timestamp("p_revieweddate", row.ReviewedDate),
Int16("p_accepted", row.Accepted),
Timestamp("p_accepteddate", row.AcceptedDate),
String("p_rejectedby", row.RejectedBy),
Timestamp("p_rejecteddate", row.RejectedDate),
String("p_rejectedreason", row.RejectedReason),
Timestamp("p_duedate", row.DueDate),
String("p_acceptedby", row.AcceptedBy),
String("p_comments", row.Comments),
Timestamp("p_estcompletedate", row.EstimatedCompletionDate),
String("p_nextaction", row.NextAction),
Int16("p_recordstatus", row.RecordStatus),
UUID("p_globalid", row.GlobalID),
String("p_created_user", row.CreatedUser),
Timestamp("p_created_date", row.CreatedDate),
String("p_last_edited_user", row.LastEditedUser),
Timestamp("p_last_edited_date", row.LastEditedDate),
Timestamp("p_firstresponsedate", row.FirstResponseDate),
Int16("p_responsedaycount", row.ResponseDayCount),
String("p_allowed", row.VerifyCorrectLocation),
String("p_xvalue", row.Xvalue),
String("p_yvalue", row.Yvalue),
String("p_validx", row.ValidX),
String("p_validy", row.ValidY),
String("p_externalid", row.ExternalID),
String("p_externalerror", row.ExternalError),
UUID("p_pointlocid", row.PointlocID),
Int16("p_notified", row.Notified),
Timestamp("p_notifieddate", row.NotifiedDate),
Int16("p_scheduled", row.Scheduled),
Timestamp("p_scheduleddate", row.ScheduledDate),
Int32("p_dog", row.Dog),
String("p_schedule_period", row.SchedulePeriod),
String("p_schedule_notes", row.ScheduleNotes),
Int32("p_spanish", row.PreferSpeakingSpanish),
Timestamp("p_creationdate", row.CreationDate),
String("p_creator", row.Creator),
Timestamp("p_editdate", row.EditDate),
String("p_editor", row.Editor),
String("p_issuesreported", row.IssuesReported),
String("p_jurisdiction", row.Jurisdiction),
String("p_notificationtimestamp", row.NotificationTimestamp),
String("p_zone", row.Zone),
String("p_zone2", row.Zone2),
JsonB("p_geometry", row.Geometry),
gisPoint,
}, nil
})
return 0, 0, nil
}
func SaveOrUpdateSpeciesAbundance(ctx context.Context, org *models.Organization, fs []*fslayer.SpeciesAbundance) (inserts uint, updates uint, err error) {
return doUpdatesViaFunction(ctx, org, fs, "SpeciesAbundance", "fieldseeker.insert_speciesabundance", func(row *fslayer.SpeciesAbundance) ([]SqlParam, error) {
gisPoint, err := pointOrNull(row.Geometry)
if err != nil {
return []SqlParam{}, err
}
return []SqlParam{
Uint("p_objectid", row.ObjectID),
Int32("p_organization_id", org.ID),
UUID("p_trapdata_id", row.TrapDataID),
String("p_species", row.Species),
Int16("p_males", row.Males),
Int16("p_unknown", row.Unknown),
Int16("p_bloodedfem", row.BloodedFemales),
Int16("p_gravidfem", row.GravidFemales),
Int16("p_larvae", row.Larvae),
Int16("p_poolstogen", row.PoolsToGenerate),
Int16("p_processed", row.Processed),
UUID("p_globalid", row.GlobalID),
String("p_created_user", row.CreatedUser),
Timestamp("p_created_date", row.CreatedDate),
String("p_last_edited_user", row.LastEditedUser),
Timestamp("p_last_edited_date", row.LastEditedDate),
Int16("p_pupae", row.Pupae),
Int16("p_eggs", row.Eggs),
Int32("p_females", row.Females),
Int32("p_total", row.TotalAdults),
Timestamp("p_creationdate", row.CreationDate),
String("p_creator", row.Creator),
Timestamp("p_editdate", row.EditDate),
String("p_editor", row.Editor),
Int32("p_yearweek", row.YearWeek),
Float64("p_globalzscore", row.GlobalZScore),
Float64("p_r7score", row.R7Score),
Float64("p_r8score", row.R8Score),
String("p_h3r7", row.H3r7),
String("p_h3r8", row.H3r8),
JsonB("p_geometry", row.Geometry),
gisPoint,
}, nil
})
return 0, 0, nil
}
func SaveOrUpdateStormDrain(ctx context.Context, org *models.Organization, fs []*fslayer.StormDrain) (inserts uint, updates uint, err error) {
return doUpdatesViaFunction(ctx, org, fs, "StormDrain", "fieldseeker.insert_stormdrain", func(row *fslayer.StormDrain) ([]SqlParam, error) {
gisPoint, err := pointOrNull(row.Geometry)
if err != nil {
return []SqlParam{}, err
}
return []SqlParam{
Uint("p_objectid", row.ObjectID),
Int32("p_organization_id", org.ID),
Timestamp("p_nexttreatmentdate", row.NextTreatmentDate),
Timestamp("p_lasttreatdate", row.LastTreatDate),
String("p_lastaction", row.LastAction),
String("p_symbology", row.Symbology),
UUID("p_globalid", row.GlobalID),
String("p_created_user", row.CreatedUser),
Timestamp("p_created_date", row.CreatedDate),
String("p_last_edited_user", row.LastEditedUser),
Timestamp("p_last_edited_date", row.LastEditedDate),
String("p_laststatus", row.LastStatus),
String("p_zone", row.Zone),
String("p_zone2", row.Zone2),
Timestamp("p_creationdate", row.CreationDate),
String("p_creator", row.Creator),
Timestamp("p_editdate", row.EditDate),
String("p_editor", row.Editor),
String("p_type", row.Type),
String("p_jurisdiction", row.Jurisdiction),
JsonB("p_geometry", row.Geometry),
gisPoint,
}, nil
})
return 0, 0, nil
}
func SaveOrUpdateTracklog(ctx context.Context, org *models.Organization, fs []*fslayer.Tracklog) (inserts uint, updates uint, err error) {
log.Warn().Msg("Ignoring RodentInspection data")
return 0, 0, nil
/*
return doUpdatesViaFunction(ctx, org, fs, "Tracklog", "fieldseeker.insert_tracklog", func(row *fslayer.Tracklog) ([]SqlParam, error) {
return []SqlParam{
Uint("p_objectid", row.ObjectID),
}, nil
})
*/
}
func SaveOrUpdateTrapLocation(ctx context.Context, org *models.Organization, fs []*fslayer.TrapLocation) (inserts uint, updates uint, err error) {
return doUpdatesViaFunction(ctx, org, fs, "TrapLocation", "fieldseeker.insert_traplocation", func(row *fslayer.TrapLocation) ([]SqlParam, error) {
gisPoint, err := pointOrNull(row.Geometry)
if err != nil {
return []SqlParam{}, err
}
return []SqlParam{
Uint("p_objectid", row.ObjectID),
Int32("p_organization_id", org.ID),
String("p_name", row.Name),
String("p_zone", row.Zone),
String("p_habitat", row.Habitat),
String("p_priority", row.Priority),
String("p_usetype", row.UseType),
Int16("p_active", row.Active),
String("p_description", row.Description),
String("p_accessdesc", row.AccessDescription),
String("p_comments", row.Comments),
String("p_externalid", row.ExternalID),
Timestamp("p_nextactiondatescheduled", row.NextScheduledAction),
String("p_zone2", row.Zone2),
Int32("p_locationnumber", row.Locationnumber),
UUID("p_globalid", row.GlobalID),
String("p_created_user", row.CreatedUser),
Timestamp("p_created_date", row.CreatedDate),
String("p_last_edited_user", row.LastEditedUser),
Timestamp("p_last_edited_date", row.LastEditedDate),
Int16("p_gatewaysync", row.GatewaySync),
Int32("p_route", row.Route),
Int32("p_set_dow", row.SetDayOfWeek),
Int32("p_route_order", row.RouteOrder),
String("p_vectorsurvsiteid", row.VectorsurvsiteID),
Timestamp("p_creationdate", row.CreationDate),
String("p_creator", row.Creator),
Timestamp("p_editdate", row.EditDate),
String("p_editor", row.Editor),
String("p_h3r7", row.H3r7),
String("p_h3r8", row.H3r8),
JsonB("p_geometry", row.Geometry),
gisPoint,
}, nil
})
return 0, 0, nil
}
func SaveOrUpdateTrapData(ctx context.Context, org *models.Organization, fs []*fslayer.TrapData) (inserts uint, updates uint, err error) {
return doUpdatesViaFunction(ctx, org, fs, "TrapData", "fieldseeker.insert_trapdata", func(row *fslayer.TrapData) ([]SqlParam, error) {
gisPoint, err := pointOrNull(row.Geometry)
if err != nil {
return []SqlParam{}, err
}
return []SqlParam{
Uint("p_objectid", row.ObjectID),
Int32("p_organization_id", org.ID),
String("p_traptype", row.TrapType),
String("p_trapactivitytype", row.TrapActivityType),
Timestamp("p_startdatetime", row.Start),
Timestamp("p_enddatetime", row.Finish),
String("p_comments", row.Comments),
String("p_idbytech", row.TechIdentifyingSpeciesInLab),
String("p_sortbytech", row.TechSortingTrapResultsInLab),
Int16("p_processed", row.Processed),
String("p_sitecond", row.SiteConditions),
String("p_locationname", row.LocationName),
Int16("p_recordstatus", row.RecordStatus),
Int16("p_reviewed", row.Reviewed),
String("p_reviewedby", row.ReviewedBy),
Timestamp("p_revieweddate", row.ReviewedDate),
String("p_trapcondition", row.TrapCondition),
Int16("p_trapnights", row.TrapNights),
String("p_zone", row.Zone),
String("p_zone2", row.Zone2),
UUID("p_globalid", row.GlobalID),
String("p_created_user", row.CreatedUser),
Timestamp("p_created_date", row.CreatedDate),
String("p_last_edited_user", row.LastEditedUser),
Timestamp("p_last_edited_date", row.LastEditedDate),
UUID("p_srid", row.SrID),
String("p_fieldtech", row.FieldTech),
Int16("p_gatewaysync", row.GatewaySync),
UUID("p_loc_id", row.LocID),
Float64("p_voltage", row.Voltage),
String("p_winddir", row.Winddir),
Float64("p_windspeed", row.Windspeed),
Float64("p_avetemp", row.Avetemp),
Float64("p_raingauge", row.Raingauge),
Int16("p_lr", row.LandingRate),
Int32("p_field", row.Field),
String("p_vectorsurvtrapdataid", row.VectorsurvtrapdataID),
String("p_vectorsurvtraplocationid", row.VectorsurvtraplocationID),
Timestamp("p_creationdate", row.CreationDate),
String("p_creator", row.Creator),
Timestamp("p_editdate", row.EditDate),
String("p_editor", row.Editor),
String("p_lure", row.Lure),
JsonB("p_geometry", row.Geometry),
gisPoint,
}, nil
})
return 0, 0, nil
}
func SaveOrUpdateTimeCard(ctx context.Context, org *models.Organization, fs []*fslayer.TimeCard) (inserts uint, updates uint, err error) {
return doUpdatesViaFunction(ctx, org, fs, "TimeCard", "fieldseeker.insert_timecard", func(row *fslayer.TimeCard) ([]SqlParam, error) {
gisPoint, err := pointOrNull(row.Geometry)
if err != nil {
return []SqlParam{}, err
}
return []SqlParam{
Uint("p_objectid", row.ObjectID),
Int32("p_organization_id", org.ID),
String("p_activity", row.Activity),
Timestamp("p_startdatetime", row.Start),
Timestamp("p_enddatetime", row.Finish),
String("p_comments", row.Comments),
String("p_externalid", row.ExternalID),
String("p_equiptype", row.EquipmentType),
String("p_locationname", row.LocationName),
String("p_zone", row.Zone),
String("p_zone2", row.Zone2),
UUID("p_globalid", row.GlobalID),
String("p_created_user", row.CreatedUser),
Timestamp("p_created_date", row.CreatedDate),
String("p_last_edited_user", row.LastEditedUser),
Timestamp("p_last_edited_date", row.LastEditedDate),
UUID("p_linelocid", row.LinelocID),
UUID("p_pointlocid", row.PointlocID),
UUID("p_polygonlocid", row.PolygonlocID),
UUID("p_lclocid", row.LclocID),
UUID("p_samplelocid", row.SamplelocID),
UUID("p_srid", row.SrID),
UUID("p_traplocid", row.TraplocID),
String("p_fieldtech", row.FieldTech),
Timestamp("p_creationdate", row.CreationDate),
String("p_creator", row.Creator),
Timestamp("p_editdate", row.EditDate),
String("p_editor", row.Editor),
UUID("p_rodentlocid", row.RodentlocID),
JsonB("p_geometry", row.Geometry),
gisPoint,
}, nil
})
return 0, 0, nil
}
func SaveOrUpdateTreatment(ctx context.Context, org *models.Organization, fs []*fslayer.Treatment) (inserts uint, updates uint, err error) {
return doUpdatesViaFunction(ctx, org, fs, "Treatment", "fieldseeker.insert_treatment", func(row *fslayer.Treatment) ([]SqlParam, error) {
gisPoint, err := pointOrNull(row.Geometry)
if err != nil {
return []SqlParam{}, err
}
return []SqlParam{
Uint("p_objectid", row.ObjectID),
Int32("p_organization_id", org.ID),
String("p_activity", row.Activity),
Float64("p_treatarea", row.AreaTreated),
String("p_areaunit", row.AreaUnit),
String("p_product", row.Product),
Float64("p_qty", row.Quantity),
String("p_qtyunit", row.QuantityUnit),
String("p_method", row.Method),
String("p_equiptype", row.EquipmentType),
String("p_comments", row.Comments),
Float64("p_avetemp", row.AverageTemperature),
Float64("p_windspeed", row.WindSpeed),
String("p_winddir", row.WindDirection),
Float64("p_raingauge", row.RainGauge),
Timestamp("p_startdatetime", row.Start),
Timestamp("p_enddatetime", row.Finish),
UUID("p_insp_id", row.InspID),
Int16("p_reviewed", row.Reviewed),
String("p_reviewedby", row.ReviewedBy),
Timestamp("p_revieweddate", row.ReviewedDate),
String("p_locationname", row.LocationName),
String("p_zone", row.Zone),
Int16("p_warningoverride", row.WarningOverride),
Int16("p_recordstatus", row.RecordStatus),
String("p_zone2", row.Zone2),
Float64("p_treatacres", row.TreatedAcres),
Int16("p_tirecount", row.TireCount),
Int16("p_cbcount", row.CatchBasinCount),
Int16("p_containercount", row.ContainerCount),
UUID("p_globalid", row.GlobalID),
Float64("p_treatmentlength", row.TreatmentLength),
Float64("p_treatmenthours", row.TreatmentHours),
String("p_treatmentlengthunits", row.TreatmentLengthUnits),
UUID("p_linelocid", row.LinelocID),
UUID("p_pointlocid", row.PointlocID),
UUID("p_polygonlocid", row.PolygonlocID),
UUID("p_srid", row.SrID),
UUID("p_sdid", row.SdID),
UUID("p_barrierrouteid", row.BarrierrouteID),
UUID("p_ulvrouteid", row.UlvrouteID),
String("p_fieldtech", row.FieldTech),
UUID("p_ptaid", row.PtaID),
Float64("p_flowrate", row.Flowrate),
String("p_habitat", row.Habitat),
Float64("p_treathectares", row.TreatHectares),
String("p_invloc", row.InventoryLocation),
String("p_temp_sitecond", row.TempConditions),
String("p_sitecond", row.Conditions),
Float64("p_totalcostprodcut", row.TotalCostProduct),
Timestamp("p_creationdate", row.CreationDate),
String("p_creator", row.Creator),
Timestamp("p_editdate", row.EditDate),
String("p_editor", row.Editor),
String("p_targetspecies", row.TargetSpecies),
JsonB("p_geometry", row.Geometry),
gisPoint,
}, nil
})
return 0, 0, nil
}
func SaveOrUpdateTreatmentArea(ctx context.Context, org *models.Organization, fs []*fslayer.TreatmentArea) (inserts uint, updates uint, err error) {
return doUpdatesViaFunction(ctx, org, fs, "TreatmentArea", "fieldseeker.insert_treatmentarea", func(row *fslayer.TreatmentArea) ([]SqlParam, error) {
gisPoint, err := polygonOrNull(row.Geometry)
if err != nil {
return []SqlParam{}, err
}
gisPoint = NullParam{"p_geospatial"}
return []SqlParam{
Uint("p_objectid", row.ObjectID),
Int32("p_organization_id", org.ID),
UUID("p_treat_id", row.TreatID),
UUID("p_session_id", row.SessionID),
Timestamp("p_treatdate", row.TreatmentDate),
String("p_comments", row.Comments),
UUID("p_globalid", row.GlobalID),
String("p_created_user", row.CreatedUser),
Timestamp("p_created_date", row.CreatedDate),
String("p_last_edited_user", row.LastEditedUser),
Timestamp("p_last_edited_date", row.LastEditedDate),
Int16("p_notified", row.Notified),
String("p_type", row.Type),
Timestamp("p_creationdate", row.CreationDate),
String("p_creator", row.Creator),
Timestamp("p_editdate", row.EditDate),
String("p_editor", row.Editor),
Float64("p_shape__area", row.ShapeArea),
Float64("p_shape__length", row.ShapeLength),
JsonB("p_geometry", row.Geometry),
gisPoint,
}, nil
})
return 0, 0, nil
}
func SaveOrUpdateULVSprayRoute(ctx context.Context, org *models.Organization, fs []*fslayer.ULVSprayRoute) (inserts uint, updates uint, err error) {
log.Warn().Msg("Ignoring RodentInspection data")
return 0, 0, nil
/*
return doUpdatesViaFunction(ctx, org, fs, "ULVSprayRoute", "fieldseeker.insert_ulvsprayroute", func(row *fslayer.ULVSprayRoute) ([]SqlParam, error) {
return []SqlParam{
Uint("p_objectid", row.ObjectID),
}, nil
})
*/
}
func SaveOrUpdateZones(ctx context.Context, org *models.Organization, fs []*fslayer.Zones) (inserts uint, updates uint, err error) {
return doUpdatesViaFunction(ctx, org, fs, "Zones", "fieldseeker.insert_zones", func(row *fslayer.Zones) ([]SqlParam, error) {
gisPoint, err := polygonOrNull(row.Geometry)
if err != nil {
return []SqlParam{}, err
}
// At this point we've got data that's bad and can't actually be inserted in the database
// so let's just always make the geo null
gisPoint = NullParam{"p_geospatial"}
return []SqlParam{
Uint("p_objectid", row.ObjectID),
Int32("p_organization_id", org.ID),
String("p_name", row.Name),
UUID("p_globalid", row.GlobalID),
String("p_created_user", row.CreatedUser),
Timestamp("p_created_date", row.CreatedDate),
String("p_last_edited_user", row.LastEditedUser),
Timestamp("p_last_edited_date", row.LastEditedDate),
Int32("p_active", row.Active),
Timestamp("p_creationdate", row.CreationDate),
String("p_creator", row.Creator),
Timestamp("p_editdate", row.EditDate),
String("p_editor", row.Editor),
Float64("p_shape__area", row.ShapeArea),
Float64("p_shape__length", row.ShapeLength),
JsonB("p_geometry", row.Geometry),
gisPoint,
}, nil
})
return 0, 0, nil
}
func SaveOrUpdateZones2(ctx context.Context, org *models.Organization, fs []*fslayer.Zones2) (inserts uint, updates uint, err error) {
return doUpdatesViaFunction(ctx, org, fs, "Zones2", "fieldseeker.insert_zones2", func(row *fslayer.Zones2) ([]SqlParam, error) {
gisPoint, err := polygonOrNull(row.Geometry)
if err != nil {
return []SqlParam{}, err
}
// At this point we've got data that's bad and can't actually be inserted in the database
// so let's just always make the geo null
gisPoint = NullParam{"p_geospatial"}
return []SqlParam{
Uint("p_objectid", row.ObjectID),
Int32("p_organization_id", org.ID),
String("p_name", row.Name),
UUID("p_globalid", row.GlobalID),
String("p_created_user", row.CreatedUser),
Timestamp("p_created_date", row.CreatedDate),
String("p_last_edited_user", row.LastEditedUser),
Timestamp("p_last_edited_date", row.LastEditedDate),
Timestamp("p_creationdate", row.CreationDate),
String("p_creator", row.Creator),
Timestamp("p_editdate", row.EditDate),
String("p_editor", row.Editor),
Float64("p_shape__area", row.ShapeArea),
Float64("p_shape__length", row.ShapeLength),
JsonB("p_geometry", row.Geometry),
gisPoint,
}, nil
})
return 0, 0, nil
}
type InsertResultRow struct {
Inserted bool `db:"row_inserted"`
Version int `db:"version_num"`
}
type rowConverter[T any] func(*T) ([]SqlParam, error)
func doUpdatesViaFunction[T any](ctx context.Context, org *models.Organization, fs []*T, table string, procedure string, converter rowConverter[T]) (inserts uint, updates uint, err error) {
//log.Info().Int("rows", len(fs)).Msg("Processing RodentLocation")
for _, row := range fs {
params, err := converter(row)
if err != nil {
return inserts, updates, fmt.Errorf("Failed to convert row '%s': %w", row, err)
}
q := queryStoredProcedure(procedure, params...)
query := psql.RawQuery(q)
result, err := bob.One[InsertResultRow](ctx, PGInstance.BobDB, query, scan.StructMapper[InsertResultRow]())
if err != nil {
log.Error().Str("query", q).Msg("Query failed")
return inserts, updates, fmt.Errorf("Failed to execute %s: %w", procedure, err)
}
if result.Inserted {
if result.Version == 1 {
inserts += 1
} else {
updates += 1
}
}
}
return inserts, updates, err
}
func toUUID(u googleuuid.UUID) omitnull.Val[uuid.UUID] {
bytes := u[:]
converted, err := uuid.FromBytes(bytes)
if err != nil {
log.Warn().Str("uuid", u.String()).Msg("Failed to convert uuid")
return omitnull.FromPtr[uuid.UUID](nil)
}
return omitnull.From(converted)
}
func toObjectID(o uint) omit.Val[int64] {
return omit.From[int64](int64(o))
}