Make signals include the object they are attached to (pool, report)

This means pushing the types into the common types module, which
required a refactor of a bunch of other libraries.
This commit is contained in:
Eli Ribble 2026-03-21 01:19:36 +00:00
parent ddc63bfa91
commit 9b6cacda0e
No known key found for this signature in database
18 changed files with 1135 additions and 262 deletions

View file

@ -10,7 +10,7 @@ import (
)
type contentListSignal struct {
Signals []platform.Signal `json:"signals"`
Signals []*platform.Signal `json:"signals"`
}
func listSignal(ctx context.Context, r *http.Request, user platform.User, query queryParams) (*contentListSignal, *nhttp.ErrorWithStatus) {

View file

@ -78,15 +78,6 @@ var Signals = Table[
Generated: false,
AutoIncr: false,
},
Title: column{
Name: "title",
DBType: "text",
Default: "",
Comment: "",
Nullable: false,
Generated: false,
AutoIncr: false,
},
Type: column{
Name: "type_",
DBType: "public.signaltype",
@ -123,6 +114,24 @@ var Signals = Table[
Generated: true,
AutoIncr: false,
},
FeaturePoolFeatureID: column{
Name: "feature_pool_feature_id",
DBType: "integer",
Default: "NULL",
Comment: "",
Nullable: true,
Generated: false,
AutoIncr: false,
},
ReportID: column{
Name: "report_id",
DBType: "integer",
Default: "NULL",
Comment: "",
Nullable: true,
Generated: false,
AutoIncr: false,
},
},
Indexes: signalIndexes{
SignalPkey: index{
@ -201,6 +210,15 @@ var Signals = Table[
ForeignTable: "user_",
ForeignColumns: []string{"id"},
},
SignalSignalFeaturePoolFeatureIDFkey: foreignKey{
constraint: constraint{
Name: "signal.signal_feature_pool_feature_id_fkey",
Columns: []string{"feature_pool_feature_id"},
Comment: "",
},
ForeignTable: "feature_pool",
ForeignColumns: []string{"feature_id"},
},
SignalSignalOrganizationIDFkey: foreignKey{
constraint: constraint{
Name: "signal.signal_organization_id_fkey",
@ -210,6 +228,15 @@ var Signals = Table[
ForeignTable: "organization",
ForeignColumns: []string{"id"},
},
SignalSignalReportIDFkey: foreignKey{
constraint: constraint{
Name: "signal.signal_report_id_fkey",
Columns: []string{"report_id"},
Comment: "",
},
ForeignTable: "publicreport.report",
ForeignColumns: []string{"id"},
},
SignalSignalSiteIDFkey: foreignKey{
constraint: constraint{
Name: "signal.signal_site_id_fkey",
@ -222,6 +249,14 @@ var Signals = Table[
},
Checks: signalChecks{
CheckExclusiveReference: check{
constraint: constraint{
Name: "check_exclusive_reference",
Columns: []string{"feature_pool_feature_id", "report_id"},
Comment: "",
},
Expression: "((feature_pool_feature_id IS NULL) OR (report_id IS NULL))",
},
ValidLocationTypes: check{
constraint: constraint{
Name: "valid_location_types",
@ -235,23 +270,24 @@ var Signals = Table[
}
type signalColumns struct {
Addressed column
Addressor column
Created column
Creator column
ID column
OrganizationID column
Species column
Title column
Type column
SiteID column
Location column
LocationType column
Addressed column
Addressor column
Created column
Creator column
ID column
OrganizationID column
Species column
Type column
SiteID column
Location column
LocationType column
FeaturePoolFeatureID column
ReportID column
}
func (c signalColumns) AsSlice() []column {
return []column{
c.Addressed, c.Addressor, c.Created, c.Creator, c.ID, c.OrganizationID, c.Species, c.Title, c.Type, c.SiteID, c.Location, c.LocationType,
c.Addressed, c.Addressor, c.Created, c.Creator, c.ID, c.OrganizationID, c.Species, c.Type, c.SiteID, c.Location, c.LocationType, c.FeaturePoolFeatureID, c.ReportID,
}
}
@ -268,15 +304,17 @@ func (i signalIndexes) AsSlice() []index {
}
type signalForeignKeys struct {
SignalSignalAddressorFkey foreignKey
SignalSignalCreatorFkey foreignKey
SignalSignalOrganizationIDFkey foreignKey
SignalSignalSiteIDFkey foreignKey
SignalSignalAddressorFkey foreignKey
SignalSignalCreatorFkey foreignKey
SignalSignalFeaturePoolFeatureIDFkey foreignKey
SignalSignalOrganizationIDFkey foreignKey
SignalSignalReportIDFkey foreignKey
SignalSignalSiteIDFkey foreignKey
}
func (f signalForeignKeys) AsSlice() []foreignKey {
return []foreignKey{
f.SignalSignalAddressorFkey, f.SignalSignalCreatorFkey, f.SignalSignalOrganizationIDFkey, f.SignalSignalSiteIDFkey,
f.SignalSignalAddressorFkey, f.SignalSignalCreatorFkey, f.SignalSignalFeaturePoolFeatureIDFkey, f.SignalSignalOrganizationIDFkey, f.SignalSignalReportIDFkey, f.SignalSignalSiteIDFkey,
}
}
@ -287,11 +325,12 @@ func (u signalUniques) AsSlice() []constraint {
}
type signalChecks struct {
ValidLocationTypes check
CheckExclusiveReference check
ValidLocationTypes check
}
func (c signalChecks) AsSlice() []check {
return []check{
c.ValidLocationTypes,
c.CheckExclusiveReference, c.ValidLocationTypes,
}
}

View file

@ -0,0 +1,4 @@
-- +goose up
ALTER TABLE signal DROP COLUMN title;
-- +goose down
ALTER TABLE signal ADD COLUMN title TEXT NOT NULL;

View file

@ -0,0 +1,12 @@
-- +goose Up
ALTER TABLE signal ADD COLUMN feature_pool_feature_id INTEGER REFERENCES feature_pool(feature_id);
ALTER TABLE signal ADD COLUMN report_id INTEGER REFERENCES publicreport.report(id);
ALTER TABLE signal
ADD CONSTRAINT check_exclusive_reference
CHECK (
(feature_pool_feature_id IS NULL OR report_id IS NULL)
);
-- +goose Down
ALTER TABLE signal DROP CONSTRAINT check_exclusive_reference;
ALTER TABLE signal DROP COLUMN report_id;
ALTER TABLE signal DROP COLUMN feature_pool_feature_id;

View file

@ -45,8 +45,9 @@ type FeaturePoolsQuery = *psql.ViewQuery[*FeaturePool, FeaturePoolSlice]
// featurePoolR is where relationships are stored.
type featurePoolR struct {
Feature *Feature // feature_pool.feature_pool_feature_id_fkey
ReviewTaskPools ReviewTaskPoolSlice // review_task_pool.review_task_pool_feature_pool_fkey
Feature *Feature // feature_pool.feature_pool_feature_id_fkey
ReviewTaskPools ReviewTaskPoolSlice // review_task_pool.review_task_pool_feature_pool_fkey
FeaturePoolFeatureSignals SignalSlice // signal.signal_feature_pool_feature_id_fkey
}
func buildFeaturePoolColumns(alias string) featurePoolColumns {
@ -465,6 +466,30 @@ func (os FeaturePoolSlice) ReviewTaskPools(mods ...bob.Mod[*dialect.SelectQuery]
)...)
}
// FeaturePoolFeatureSignals starts a query for related objects on signal
func (o *FeaturePool) FeaturePoolFeatureSignals(mods ...bob.Mod[*dialect.SelectQuery]) SignalsQuery {
return Signals.Query(append(mods,
sm.Where(Signals.Columns.FeaturePoolFeatureID.EQ(psql.Arg(o.FeatureID))),
)...)
}
func (os FeaturePoolSlice) FeaturePoolFeatureSignals(mods ...bob.Mod[*dialect.SelectQuery]) SignalsQuery {
pkFeatureID := make(pgtypes.Array[int32], 0, len(os))
for _, o := range os {
if o == nil {
continue
}
pkFeatureID = append(pkFeatureID, o.FeatureID)
}
PKArgExpr := psql.Select(sm.Columns(
psql.F("unnest", psql.Cast(psql.Arg(pkFeatureID), "integer[]")),
))
return Signals.Query(append(mods,
sm.Where(psql.Group(Signals.Columns.FeaturePoolFeatureID).OP("IN", PKArgExpr)),
)...)
}
func attachFeaturePoolFeature0(ctx context.Context, exec bob.Executor, count int, featurePool0 *FeaturePool, feature1 *Feature) (*FeaturePool, error) {
setter := &FeaturePoolSetter{
FeatureID: omit.From(feature1.ID),
@ -581,6 +606,74 @@ func (featurePool0 *FeaturePool) AttachReviewTaskPools(ctx context.Context, exec
return nil
}
func insertFeaturePoolFeaturePoolFeatureSignals0(ctx context.Context, exec bob.Executor, signals1 []*SignalSetter, featurePool0 *FeaturePool) (SignalSlice, error) {
for i := range signals1 {
signals1[i].FeaturePoolFeatureID = omitnull.From(featurePool0.FeatureID)
}
ret, err := Signals.Insert(bob.ToMods(signals1...)).All(ctx, exec)
if err != nil {
return ret, fmt.Errorf("insertFeaturePoolFeaturePoolFeatureSignals0: %w", err)
}
return ret, nil
}
func attachFeaturePoolFeaturePoolFeatureSignals0(ctx context.Context, exec bob.Executor, count int, signals1 SignalSlice, featurePool0 *FeaturePool) (SignalSlice, error) {
setter := &SignalSetter{
FeaturePoolFeatureID: omitnull.From(featurePool0.FeatureID),
}
err := signals1.UpdateAll(ctx, exec, *setter)
if err != nil {
return nil, fmt.Errorf("attachFeaturePoolFeaturePoolFeatureSignals0: %w", err)
}
return signals1, nil
}
func (featurePool0 *FeaturePool) InsertFeaturePoolFeatureSignals(ctx context.Context, exec bob.Executor, related ...*SignalSetter) error {
if len(related) == 0 {
return nil
}
var err error
signals1, err := insertFeaturePoolFeaturePoolFeatureSignals0(ctx, exec, related, featurePool0)
if err != nil {
return err
}
featurePool0.R.FeaturePoolFeatureSignals = append(featurePool0.R.FeaturePoolFeatureSignals, signals1...)
for _, rel := range signals1 {
rel.R.FeaturePoolFeatureFeaturePool = featurePool0
}
return nil
}
func (featurePool0 *FeaturePool) AttachFeaturePoolFeatureSignals(ctx context.Context, exec bob.Executor, related ...*Signal) error {
if len(related) == 0 {
return nil
}
var err error
signals1 := SignalSlice(related)
_, err = attachFeaturePoolFeaturePoolFeatureSignals0(ctx, exec, len(related), signals1, featurePool0)
if err != nil {
return err
}
featurePool0.R.FeaturePoolFeatureSignals = append(featurePool0.R.FeaturePoolFeatureSignals, signals1...)
for _, rel := range related {
rel.R.FeaturePoolFeatureFeaturePool = featurePool0
}
return nil
}
type featurePoolWhere[Q psql.Filterable] struct {
FeatureID psql.WhereMod[Q, int32]
Condition psql.WhereMod[Q, enums.Poolconditiontype]
@ -633,6 +726,20 @@ func (o *FeaturePool) Preload(name string, retrieved any) error {
}
}
return nil
case "FeaturePoolFeatureSignals":
rels, ok := retrieved.(SignalSlice)
if !ok {
return fmt.Errorf("featurePool cannot load %T as %q", retrieved, name)
}
o.R.FeaturePoolFeatureSignals = rels
for _, rel := range rels {
if rel != nil {
rel.R.FeaturePoolFeatureFeaturePool = o
}
}
return nil
default:
return fmt.Errorf("featurePool has no relationship %q", name)
}
@ -661,8 +768,9 @@ func buildFeaturePoolPreloader() featurePoolPreloader {
}
type featurePoolThenLoader[Q orm.Loadable] struct {
Feature func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q]
ReviewTaskPools func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q]
Feature func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q]
ReviewTaskPools func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q]
FeaturePoolFeatureSignals func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q]
}
func buildFeaturePoolThenLoader[Q orm.Loadable]() featurePoolThenLoader[Q] {
@ -672,6 +780,9 @@ func buildFeaturePoolThenLoader[Q orm.Loadable]() featurePoolThenLoader[Q] {
type ReviewTaskPoolsLoadInterface interface {
LoadReviewTaskPools(context.Context, bob.Executor, ...bob.Mod[*dialect.SelectQuery]) error
}
type FeaturePoolFeatureSignalsLoadInterface interface {
LoadFeaturePoolFeatureSignals(context.Context, bob.Executor, ...bob.Mod[*dialect.SelectQuery]) error
}
return featurePoolThenLoader[Q]{
Feature: thenLoadBuilder[Q](
@ -686,6 +797,12 @@ func buildFeaturePoolThenLoader[Q orm.Loadable]() featurePoolThenLoader[Q] {
return retrieved.LoadReviewTaskPools(ctx, exec, mods...)
},
),
FeaturePoolFeatureSignals: thenLoadBuilder[Q](
"FeaturePoolFeatureSignals",
func(ctx context.Context, exec bob.Executor, retrieved FeaturePoolFeatureSignalsLoadInterface, mods ...bob.Mod[*dialect.SelectQuery]) error {
return retrieved.LoadFeaturePoolFeatureSignals(ctx, exec, mods...)
},
),
}
}
@ -801,3 +918,67 @@ func (os FeaturePoolSlice) LoadReviewTaskPools(ctx context.Context, exec bob.Exe
return nil
}
// LoadFeaturePoolFeatureSignals loads the featurePool's FeaturePoolFeatureSignals into the .R struct
func (o *FeaturePool) LoadFeaturePoolFeatureSignals(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error {
if o == nil {
return nil
}
// Reset the relationship
o.R.FeaturePoolFeatureSignals = nil
related, err := o.FeaturePoolFeatureSignals(mods...).All(ctx, exec)
if err != nil {
return err
}
for _, rel := range related {
rel.R.FeaturePoolFeatureFeaturePool = o
}
o.R.FeaturePoolFeatureSignals = related
return nil
}
// LoadFeaturePoolFeatureSignals loads the featurePool's FeaturePoolFeatureSignals into the .R struct
func (os FeaturePoolSlice) LoadFeaturePoolFeatureSignals(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error {
if len(os) == 0 {
return nil
}
signals, err := os.FeaturePoolFeatureSignals(mods...).All(ctx, exec)
if err != nil {
return err
}
for _, o := range os {
if o == nil {
continue
}
o.R.FeaturePoolFeatureSignals = nil
}
for _, o := range os {
if o == nil {
continue
}
for _, rel := range signals {
if !rel.FeaturePoolFeatureID.IsValue() {
continue
}
if !(rel.FeaturePoolFeatureID.IsValue() && o.FeatureID == rel.FeaturePoolFeatureID.MustGet()) {
continue
}
rel.R.FeaturePoolFeatureFeaturePool = o
o.R.FeaturePoolFeatureSignals = append(o.R.FeaturePoolFeatureSignals, rel)
}
}
return nil
}

View file

@ -81,6 +81,7 @@ type publicreportReportR struct {
ReportLogs PublicreportReportLogSlice // publicreport.report_log.report_log_report_id_fkey
Water *PublicreportWater // publicreport.water.water_report_id_fkey
ReportTexts ReportTextSlice // report_text.report_text_report_id_fkey
Signals SignalSlice // signal.signal_report_id_fkey
}
func buildPublicreportReportColumns(alias string) publicreportReportColumns {
@ -1186,6 +1187,30 @@ func (os PublicreportReportSlice) ReportTexts(mods ...bob.Mod[*dialect.SelectQue
)...)
}
// Signals starts a query for related objects on signal
func (o *PublicreportReport) Signals(mods ...bob.Mod[*dialect.SelectQuery]) SignalsQuery {
return Signals.Query(append(mods,
sm.Where(Signals.Columns.ReportID.EQ(psql.Arg(o.ID))),
)...)
}
func (os PublicreportReportSlice) Signals(mods ...bob.Mod[*dialect.SelectQuery]) SignalsQuery {
pkID := make(pgtypes.Array[int32], 0, len(os))
for _, o := range os {
if o == nil {
continue
}
pkID = append(pkID, o.ID)
}
PKArgExpr := psql.Select(sm.Columns(
psql.F("unnest", psql.Cast(psql.Arg(pkID), "integer[]")),
))
return Signals.Query(append(mods,
sm.Where(psql.Group(Signals.Columns.ReportID).OP("IN", PKArgExpr)),
)...)
}
func insertPublicreportReportTextJobs0(ctx context.Context, exec bob.Executor, commsTextJobs1 []*CommsTextJobSetter, publicreportReport0 *PublicreportReport) (CommsTextJobSlice, error) {
for i := range commsTextJobs1 {
commsTextJobs1[i].ReportID = omitnull.From(publicreportReport0.ID)
@ -1843,6 +1868,74 @@ func (publicreportReport0 *PublicreportReport) AttachReportTexts(ctx context.Con
return nil
}
func insertPublicreportReportSignals0(ctx context.Context, exec bob.Executor, signals1 []*SignalSetter, publicreportReport0 *PublicreportReport) (SignalSlice, error) {
for i := range signals1 {
signals1[i].ReportID = omitnull.From(publicreportReport0.ID)
}
ret, err := Signals.Insert(bob.ToMods(signals1...)).All(ctx, exec)
if err != nil {
return ret, fmt.Errorf("insertPublicreportReportSignals0: %w", err)
}
return ret, nil
}
func attachPublicreportReportSignals0(ctx context.Context, exec bob.Executor, count int, signals1 SignalSlice, publicreportReport0 *PublicreportReport) (SignalSlice, error) {
setter := &SignalSetter{
ReportID: omitnull.From(publicreportReport0.ID),
}
err := signals1.UpdateAll(ctx, exec, *setter)
if err != nil {
return nil, fmt.Errorf("attachPublicreportReportSignals0: %w", err)
}
return signals1, nil
}
func (publicreportReport0 *PublicreportReport) InsertSignals(ctx context.Context, exec bob.Executor, related ...*SignalSetter) error {
if len(related) == 0 {
return nil
}
var err error
signals1, err := insertPublicreportReportSignals0(ctx, exec, related, publicreportReport0)
if err != nil {
return err
}
publicreportReport0.R.Signals = append(publicreportReport0.R.Signals, signals1...)
for _, rel := range signals1 {
rel.R.Report = publicreportReport0
}
return nil
}
func (publicreportReport0 *PublicreportReport) AttachSignals(ctx context.Context, exec bob.Executor, related ...*Signal) error {
if len(related) == 0 {
return nil
}
var err error
signals1 := SignalSlice(related)
_, err = attachPublicreportReportSignals0(ctx, exec, len(related), signals1, publicreportReport0)
if err != nil {
return err
}
publicreportReport0.R.Signals = append(publicreportReport0.R.Signals, signals1...)
for _, rel := range related {
rel.R.Report = publicreportReport0
}
return nil
}
type publicreportReportWhere[Q psql.Filterable] struct {
AddressRaw psql.WhereMod[Q, string]
AddressNumber psql.WhereMod[Q, string]
@ -2053,6 +2146,20 @@ func (o *PublicreportReport) Preload(name string, retrieved any) error {
o.R.ReportTexts = rels
for _, rel := range rels {
if rel != nil {
rel.R.Report = o
}
}
return nil
case "Signals":
rels, ok := retrieved.(SignalSlice)
if !ok {
return fmt.Errorf("publicreportReport cannot load %T as %q", retrieved, name)
}
o.R.Signals = rels
for _, rel := range rels {
if rel != nil {
rel.R.Report = o
@ -2154,6 +2261,7 @@ type publicreportReportThenLoader[Q orm.Loadable] struct {
ReportLogs func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q]
Water func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q]
ReportTexts func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q]
Signals func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q]
}
func buildPublicreportReportThenLoader[Q orm.Loadable]() publicreportReportThenLoader[Q] {
@ -2190,6 +2298,9 @@ func buildPublicreportReportThenLoader[Q orm.Loadable]() publicreportReportThenL
type ReportTextsLoadInterface interface {
LoadReportTexts(context.Context, bob.Executor, ...bob.Mod[*dialect.SelectQuery]) error
}
type SignalsLoadInterface interface {
LoadSignals(context.Context, bob.Executor, ...bob.Mod[*dialect.SelectQuery]) error
}
return publicreportReportThenLoader[Q]{
TextJobs: thenLoadBuilder[Q](
@ -2258,6 +2369,12 @@ func buildPublicreportReportThenLoader[Q orm.Loadable]() publicreportReportThenL
return retrieved.LoadReportTexts(ctx, exec, mods...)
},
),
Signals: thenLoadBuilder[Q](
"Signals",
func(ctx context.Context, exec bob.Executor, retrieved SignalsLoadInterface, mods ...bob.Mod[*dialect.SelectQuery]) error {
return retrieved.LoadSignals(ctx, exec, mods...)
},
),
}
}
@ -2915,3 +3032,67 @@ func (os PublicreportReportSlice) LoadReportTexts(ctx context.Context, exec bob.
return nil
}
// LoadSignals loads the publicreportReport's Signals into the .R struct
func (o *PublicreportReport) LoadSignals(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error {
if o == nil {
return nil
}
// Reset the relationship
o.R.Signals = nil
related, err := o.Signals(mods...).All(ctx, exec)
if err != nil {
return err
}
for _, rel := range related {
rel.R.Report = o
}
o.R.Signals = related
return nil
}
// LoadSignals loads the publicreportReport's Signals into the .R struct
func (os PublicreportReportSlice) LoadSignals(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error {
if len(os) == 0 {
return nil
}
signals, err := os.Signals(mods...).All(ctx, exec)
if err != nil {
return err
}
for _, o := range os {
if o == nil {
continue
}
o.R.Signals = nil
}
for _, o := range os {
if o == nil {
continue
}
for _, rel := range signals {
if !rel.ReportID.IsValue() {
continue
}
if !(rel.ReportID.IsValue() && o.ID == rel.ReportID.MustGet()) {
continue
}
rel.R.Report = o
o.R.Signals = append(o.R.Signals, rel)
}
}
return nil
}

View file

@ -26,18 +26,19 @@ import (
// Signal is an object representing the database table.
type Signal struct {
Addressed null.Val[time.Time] `db:"addressed" `
Addressor null.Val[int32] `db:"addressor" `
Created time.Time `db:"created" `
Creator int32 `db:"creator" `
ID int32 `db:"id,pk" `
OrganizationID int32 `db:"organization_id" `
Species null.Val[enums.Mosquitospecies] `db:"species" `
Title string `db:"title" `
Type enums.Signaltype `db:"type_" `
SiteID null.Val[int32] `db:"site_id" `
Location string `db:"location" `
LocationType null.Val[string] `db:"location_type,generated" `
Addressed null.Val[time.Time] `db:"addressed" `
Addressor null.Val[int32] `db:"addressor" `
Created time.Time `db:"created" `
Creator int32 `db:"creator" `
ID int32 `db:"id,pk" `
OrganizationID int32 `db:"organization_id" `
Species null.Val[enums.Mosquitospecies] `db:"species" `
Type enums.Signaltype `db:"type_" `
SiteID null.Val[int32] `db:"site_id" `
Location string `db:"location" `
LocationType null.Val[string] `db:"location_type,generated" `
FeaturePoolFeatureID null.Val[int32] `db:"feature_pool_feature_id" `
ReportID null.Val[int32] `db:"report_id" `
R signalR `db:"-" `
}
@ -54,48 +55,52 @@ type SignalsQuery = *psql.ViewQuery[*Signal, SignalSlice]
// signalR is where relationships are stored.
type signalR struct {
AddressorUser *User // signal.signal_addressor_fkey
CreatorUser *User // signal.signal_creator_fkey
Organization *Organization // signal.signal_organization_id_fkey
Site *Site // signal.signal_site_id_fkey
AddressorUser *User // signal.signal_addressor_fkey
CreatorUser *User // signal.signal_creator_fkey
FeaturePoolFeatureFeaturePool *FeaturePool // signal.signal_feature_pool_feature_id_fkey
Organization *Organization // signal.signal_organization_id_fkey
Report *PublicreportReport // signal.signal_report_id_fkey
Site *Site // signal.signal_site_id_fkey
}
func buildSignalColumns(alias string) signalColumns {
return signalColumns{
ColumnsExpr: expr.NewColumnsExpr(
"addressed", "addressor", "created", "creator", "id", "organization_id", "species", "title", "type_", "site_id", "location", "location_type",
"addressed", "addressor", "created", "creator", "id", "organization_id", "species", "type_", "site_id", "location", "location_type", "feature_pool_feature_id", "report_id",
).WithParent("signal"),
tableAlias: alias,
Addressed: psql.Quote(alias, "addressed"),
Addressor: psql.Quote(alias, "addressor"),
Created: psql.Quote(alias, "created"),
Creator: psql.Quote(alias, "creator"),
ID: psql.Quote(alias, "id"),
OrganizationID: psql.Quote(alias, "organization_id"),
Species: psql.Quote(alias, "species"),
Title: psql.Quote(alias, "title"),
Type: psql.Quote(alias, "type_"),
SiteID: psql.Quote(alias, "site_id"),
Location: psql.Quote(alias, "location"),
LocationType: psql.Quote(alias, "location_type"),
tableAlias: alias,
Addressed: psql.Quote(alias, "addressed"),
Addressor: psql.Quote(alias, "addressor"),
Created: psql.Quote(alias, "created"),
Creator: psql.Quote(alias, "creator"),
ID: psql.Quote(alias, "id"),
OrganizationID: psql.Quote(alias, "organization_id"),
Species: psql.Quote(alias, "species"),
Type: psql.Quote(alias, "type_"),
SiteID: psql.Quote(alias, "site_id"),
Location: psql.Quote(alias, "location"),
LocationType: psql.Quote(alias, "location_type"),
FeaturePoolFeatureID: psql.Quote(alias, "feature_pool_feature_id"),
ReportID: psql.Quote(alias, "report_id"),
}
}
type signalColumns struct {
expr.ColumnsExpr
tableAlias string
Addressed psql.Expression
Addressor psql.Expression
Created psql.Expression
Creator psql.Expression
ID psql.Expression
OrganizationID psql.Expression
Species psql.Expression
Title psql.Expression
Type psql.Expression
SiteID psql.Expression
Location psql.Expression
LocationType psql.Expression
tableAlias string
Addressed psql.Expression
Addressor psql.Expression
Created psql.Expression
Creator psql.Expression
ID psql.Expression
OrganizationID psql.Expression
Species psql.Expression
Type psql.Expression
SiteID psql.Expression
Location psql.Expression
LocationType psql.Expression
FeaturePoolFeatureID psql.Expression
ReportID psql.Expression
}
func (c signalColumns) Alias() string {
@ -110,21 +115,22 @@ func (signalColumns) AliasedAs(alias string) signalColumns {
// All values are optional, and do not have to be set
// Generated columns are not included
type SignalSetter struct {
Addressed omitnull.Val[time.Time] `db:"addressed" `
Addressor omitnull.Val[int32] `db:"addressor" `
Created omit.Val[time.Time] `db:"created" `
Creator omit.Val[int32] `db:"creator" `
ID omit.Val[int32] `db:"id,pk" `
OrganizationID omit.Val[int32] `db:"organization_id" `
Species omitnull.Val[enums.Mosquitospecies] `db:"species" `
Title omit.Val[string] `db:"title" `
Type omit.Val[enums.Signaltype] `db:"type_" `
SiteID omitnull.Val[int32] `db:"site_id" `
Location omit.Val[string] `db:"location" `
Addressed omitnull.Val[time.Time] `db:"addressed" `
Addressor omitnull.Val[int32] `db:"addressor" `
Created omit.Val[time.Time] `db:"created" `
Creator omit.Val[int32] `db:"creator" `
ID omit.Val[int32] `db:"id,pk" `
OrganizationID omit.Val[int32] `db:"organization_id" `
Species omitnull.Val[enums.Mosquitospecies] `db:"species" `
Type omit.Val[enums.Signaltype] `db:"type_" `
SiteID omitnull.Val[int32] `db:"site_id" `
Location omit.Val[string] `db:"location" `
FeaturePoolFeatureID omitnull.Val[int32] `db:"feature_pool_feature_id" `
ReportID omitnull.Val[int32] `db:"report_id" `
}
func (s SignalSetter) SetColumns() []string {
vals := make([]string, 0, 11)
vals := make([]string, 0, 12)
if !s.Addressed.IsUnset() {
vals = append(vals, "addressed")
}
@ -146,9 +152,6 @@ func (s SignalSetter) SetColumns() []string {
if !s.Species.IsUnset() {
vals = append(vals, "species")
}
if s.Title.IsValue() {
vals = append(vals, "title")
}
if s.Type.IsValue() {
vals = append(vals, "type_")
}
@ -158,6 +161,12 @@ func (s SignalSetter) SetColumns() []string {
if s.Location.IsValue() {
vals = append(vals, "location")
}
if !s.FeaturePoolFeatureID.IsUnset() {
vals = append(vals, "feature_pool_feature_id")
}
if !s.ReportID.IsUnset() {
vals = append(vals, "report_id")
}
return vals
}
@ -183,9 +192,6 @@ func (s SignalSetter) Overwrite(t *Signal) {
if !s.Species.IsUnset() {
t.Species = s.Species.MustGetNull()
}
if s.Title.IsValue() {
t.Title = s.Title.MustGet()
}
if s.Type.IsValue() {
t.Type = s.Type.MustGet()
}
@ -195,6 +201,12 @@ func (s SignalSetter) Overwrite(t *Signal) {
if s.Location.IsValue() {
t.Location = s.Location.MustGet()
}
if !s.FeaturePoolFeatureID.IsUnset() {
t.FeaturePoolFeatureID = s.FeaturePoolFeatureID.MustGetNull()
}
if !s.ReportID.IsUnset() {
t.ReportID = s.ReportID.MustGetNull()
}
}
func (s *SignalSetter) Apply(q *dialect.InsertQuery) {
@ -203,7 +215,7 @@ func (s *SignalSetter) Apply(q *dialect.InsertQuery) {
})
q.AppendValues(bob.ExpressionFunc(func(ctx context.Context, w io.StringWriter, d bob.Dialect, start int) ([]any, error) {
vals := make([]bob.Expression, 11)
vals := make([]bob.Expression, 12)
if !s.Addressed.IsUnset() {
vals[0] = psql.Arg(s.Addressed.MustGetNull())
} else {
@ -246,30 +258,36 @@ func (s *SignalSetter) Apply(q *dialect.InsertQuery) {
vals[6] = psql.Raw("DEFAULT")
}
if s.Title.IsValue() {
vals[7] = psql.Arg(s.Title.MustGet())
if s.Type.IsValue() {
vals[7] = psql.Arg(s.Type.MustGet())
} else {
vals[7] = psql.Raw("DEFAULT")
}
if s.Type.IsValue() {
vals[8] = psql.Arg(s.Type.MustGet())
if !s.SiteID.IsUnset() {
vals[8] = psql.Arg(s.SiteID.MustGetNull())
} else {
vals[8] = psql.Raw("DEFAULT")
}
if !s.SiteID.IsUnset() {
vals[9] = psql.Arg(s.SiteID.MustGetNull())
if s.Location.IsValue() {
vals[9] = psql.Arg(s.Location.MustGet())
} else {
vals[9] = psql.Raw("DEFAULT")
}
if s.Location.IsValue() {
vals[10] = psql.Arg(s.Location.MustGet())
if !s.FeaturePoolFeatureID.IsUnset() {
vals[10] = psql.Arg(s.FeaturePoolFeatureID.MustGetNull())
} else {
vals[10] = psql.Raw("DEFAULT")
}
if !s.ReportID.IsUnset() {
vals[11] = psql.Arg(s.ReportID.MustGetNull())
} else {
vals[11] = psql.Raw("DEFAULT")
}
return bob.ExpressSlice(ctx, w, d, start, vals, "", ", ", "")
}))
}
@ -279,7 +297,7 @@ func (s SignalSetter) UpdateMod() bob.Mod[*dialect.UpdateQuery] {
}
func (s SignalSetter) Expressions(prefix ...string) []bob.Expression {
exprs := make([]bob.Expression, 0, 11)
exprs := make([]bob.Expression, 0, 12)
if !s.Addressed.IsUnset() {
exprs = append(exprs, expr.Join{Sep: " = ", Exprs: []bob.Expression{
@ -330,13 +348,6 @@ func (s SignalSetter) Expressions(prefix ...string) []bob.Expression {
}})
}
if s.Title.IsValue() {
exprs = append(exprs, expr.Join{Sep: " = ", Exprs: []bob.Expression{
psql.Quote(append(prefix, "title")...),
psql.Arg(s.Title),
}})
}
if s.Type.IsValue() {
exprs = append(exprs, expr.Join{Sep: " = ", Exprs: []bob.Expression{
psql.Quote(append(prefix, "type_")...),
@ -358,6 +369,20 @@ func (s SignalSetter) Expressions(prefix ...string) []bob.Expression {
}})
}
if !s.FeaturePoolFeatureID.IsUnset() {
exprs = append(exprs, expr.Join{Sep: " = ", Exprs: []bob.Expression{
psql.Quote(append(prefix, "feature_pool_feature_id")...),
psql.Arg(s.FeaturePoolFeatureID),
}})
}
if !s.ReportID.IsUnset() {
exprs = append(exprs, expr.Join{Sep: " = ", Exprs: []bob.Expression{
psql.Quote(append(prefix, "report_id")...),
psql.Arg(s.ReportID),
}})
}
return exprs
}
@ -632,6 +657,30 @@ func (os SignalSlice) CreatorUser(mods ...bob.Mod[*dialect.SelectQuery]) UsersQu
)...)
}
// FeaturePoolFeatureFeaturePool starts a query for related objects on feature_pool
func (o *Signal) FeaturePoolFeatureFeaturePool(mods ...bob.Mod[*dialect.SelectQuery]) FeaturePoolsQuery {
return FeaturePools.Query(append(mods,
sm.Where(FeaturePools.Columns.FeatureID.EQ(psql.Arg(o.FeaturePoolFeatureID))),
)...)
}
func (os SignalSlice) FeaturePoolFeatureFeaturePool(mods ...bob.Mod[*dialect.SelectQuery]) FeaturePoolsQuery {
pkFeaturePoolFeatureID := make(pgtypes.Array[null.Val[int32]], 0, len(os))
for _, o := range os {
if o == nil {
continue
}
pkFeaturePoolFeatureID = append(pkFeaturePoolFeatureID, o.FeaturePoolFeatureID)
}
PKArgExpr := psql.Select(sm.Columns(
psql.F("unnest", psql.Cast(psql.Arg(pkFeaturePoolFeatureID), "integer[]")),
))
return FeaturePools.Query(append(mods,
sm.Where(psql.Group(FeaturePools.Columns.FeatureID).OP("IN", PKArgExpr)),
)...)
}
// Organization starts a query for related objects on organization
func (o *Signal) Organization(mods ...bob.Mod[*dialect.SelectQuery]) OrganizationsQuery {
return Organizations.Query(append(mods,
@ -656,6 +705,30 @@ func (os SignalSlice) Organization(mods ...bob.Mod[*dialect.SelectQuery]) Organi
)...)
}
// Report starts a query for related objects on publicreport.report
func (o *Signal) Report(mods ...bob.Mod[*dialect.SelectQuery]) PublicreportReportsQuery {
return PublicreportReports.Query(append(mods,
sm.Where(PublicreportReports.Columns.ID.EQ(psql.Arg(o.ReportID))),
)...)
}
func (os SignalSlice) Report(mods ...bob.Mod[*dialect.SelectQuery]) PublicreportReportsQuery {
pkReportID := make(pgtypes.Array[null.Val[int32]], 0, len(os))
for _, o := range os {
if o == nil {
continue
}
pkReportID = append(pkReportID, o.ReportID)
}
PKArgExpr := psql.Select(sm.Columns(
psql.F("unnest", psql.Cast(psql.Arg(pkReportID), "integer[]")),
))
return PublicreportReports.Query(append(mods,
sm.Where(psql.Group(PublicreportReports.Columns.ID).OP("IN", PKArgExpr)),
)...)
}
// Site starts a query for related objects on site
func (o *Signal) Site(mods ...bob.Mod[*dialect.SelectQuery]) SitesQuery {
return Sites.Query(append(mods,
@ -776,6 +849,54 @@ func (signal0 *Signal) AttachCreatorUser(ctx context.Context, exec bob.Executor,
return nil
}
func attachSignalFeaturePoolFeatureFeaturePool0(ctx context.Context, exec bob.Executor, count int, signal0 *Signal, featurePool1 *FeaturePool) (*Signal, error) {
setter := &SignalSetter{
FeaturePoolFeatureID: omitnull.From(featurePool1.FeatureID),
}
err := signal0.Update(ctx, exec, setter)
if err != nil {
return nil, fmt.Errorf("attachSignalFeaturePoolFeatureFeaturePool0: %w", err)
}
return signal0, nil
}
func (signal0 *Signal) InsertFeaturePoolFeatureFeaturePool(ctx context.Context, exec bob.Executor, related *FeaturePoolSetter) error {
var err error
featurePool1, err := FeaturePools.Insert(related).One(ctx, exec)
if err != nil {
return fmt.Errorf("inserting related objects: %w", err)
}
_, err = attachSignalFeaturePoolFeatureFeaturePool0(ctx, exec, 1, signal0, featurePool1)
if err != nil {
return err
}
signal0.R.FeaturePoolFeatureFeaturePool = featurePool1
featurePool1.R.FeaturePoolFeatureSignals = append(featurePool1.R.FeaturePoolFeatureSignals, signal0)
return nil
}
func (signal0 *Signal) AttachFeaturePoolFeatureFeaturePool(ctx context.Context, exec bob.Executor, featurePool1 *FeaturePool) error {
var err error
_, err = attachSignalFeaturePoolFeatureFeaturePool0(ctx, exec, 1, signal0, featurePool1)
if err != nil {
return err
}
signal0.R.FeaturePoolFeatureFeaturePool = featurePool1
featurePool1.R.FeaturePoolFeatureSignals = append(featurePool1.R.FeaturePoolFeatureSignals, signal0)
return nil
}
func attachSignalOrganization0(ctx context.Context, exec bob.Executor, count int, signal0 *Signal, organization1 *Organization) (*Signal, error) {
setter := &SignalSetter{
OrganizationID: omit.From(organization1.ID),
@ -824,6 +945,54 @@ func (signal0 *Signal) AttachOrganization(ctx context.Context, exec bob.Executor
return nil
}
func attachSignalReport0(ctx context.Context, exec bob.Executor, count int, signal0 *Signal, publicreportReport1 *PublicreportReport) (*Signal, error) {
setter := &SignalSetter{
ReportID: omitnull.From(publicreportReport1.ID),
}
err := signal0.Update(ctx, exec, setter)
if err != nil {
return nil, fmt.Errorf("attachSignalReport0: %w", err)
}
return signal0, nil
}
func (signal0 *Signal) InsertReport(ctx context.Context, exec bob.Executor, related *PublicreportReportSetter) error {
var err error
publicreportReport1, err := PublicreportReports.Insert(related).One(ctx, exec)
if err != nil {
return fmt.Errorf("inserting related objects: %w", err)
}
_, err = attachSignalReport0(ctx, exec, 1, signal0, publicreportReport1)
if err != nil {
return err
}
signal0.R.Report = publicreportReport1
publicreportReport1.R.Signals = append(publicreportReport1.R.Signals, signal0)
return nil
}
func (signal0 *Signal) AttachReport(ctx context.Context, exec bob.Executor, publicreportReport1 *PublicreportReport) error {
var err error
_, err = attachSignalReport0(ctx, exec, 1, signal0, publicreportReport1)
if err != nil {
return err
}
signal0.R.Report = publicreportReport1
publicreportReport1.R.Signals = append(publicreportReport1.R.Signals, signal0)
return nil
}
func attachSignalSite0(ctx context.Context, exec bob.Executor, count int, signal0 *Signal, site1 *Site) (*Signal, error) {
setter := &SignalSetter{
SiteID: omitnull.From(site1.ID),
@ -873,18 +1042,19 @@ func (signal0 *Signal) AttachSite(ctx context.Context, exec bob.Executor, site1
}
type signalWhere[Q psql.Filterable] struct {
Addressed psql.WhereNullMod[Q, time.Time]
Addressor psql.WhereNullMod[Q, int32]
Created psql.WhereMod[Q, time.Time]
Creator psql.WhereMod[Q, int32]
ID psql.WhereMod[Q, int32]
OrganizationID psql.WhereMod[Q, int32]
Species psql.WhereNullMod[Q, enums.Mosquitospecies]
Title psql.WhereMod[Q, string]
Type psql.WhereMod[Q, enums.Signaltype]
SiteID psql.WhereNullMod[Q, int32]
Location psql.WhereMod[Q, string]
LocationType psql.WhereNullMod[Q, string]
Addressed psql.WhereNullMod[Q, time.Time]
Addressor psql.WhereNullMod[Q, int32]
Created psql.WhereMod[Q, time.Time]
Creator psql.WhereMod[Q, int32]
ID psql.WhereMod[Q, int32]
OrganizationID psql.WhereMod[Q, int32]
Species psql.WhereNullMod[Q, enums.Mosquitospecies]
Type psql.WhereMod[Q, enums.Signaltype]
SiteID psql.WhereNullMod[Q, int32]
Location psql.WhereMod[Q, string]
LocationType psql.WhereNullMod[Q, string]
FeaturePoolFeatureID psql.WhereNullMod[Q, int32]
ReportID psql.WhereNullMod[Q, int32]
}
func (signalWhere[Q]) AliasedAs(alias string) signalWhere[Q] {
@ -893,18 +1063,19 @@ func (signalWhere[Q]) AliasedAs(alias string) signalWhere[Q] {
func buildSignalWhere[Q psql.Filterable](cols signalColumns) signalWhere[Q] {
return signalWhere[Q]{
Addressed: psql.WhereNull[Q, time.Time](cols.Addressed),
Addressor: psql.WhereNull[Q, int32](cols.Addressor),
Created: psql.Where[Q, time.Time](cols.Created),
Creator: psql.Where[Q, int32](cols.Creator),
ID: psql.Where[Q, int32](cols.ID),
OrganizationID: psql.Where[Q, int32](cols.OrganizationID),
Species: psql.WhereNull[Q, enums.Mosquitospecies](cols.Species),
Title: psql.Where[Q, string](cols.Title),
Type: psql.Where[Q, enums.Signaltype](cols.Type),
SiteID: psql.WhereNull[Q, int32](cols.SiteID),
Location: psql.Where[Q, string](cols.Location),
LocationType: psql.WhereNull[Q, string](cols.LocationType),
Addressed: psql.WhereNull[Q, time.Time](cols.Addressed),
Addressor: psql.WhereNull[Q, int32](cols.Addressor),
Created: psql.Where[Q, time.Time](cols.Created),
Creator: psql.Where[Q, int32](cols.Creator),
ID: psql.Where[Q, int32](cols.ID),
OrganizationID: psql.Where[Q, int32](cols.OrganizationID),
Species: psql.WhereNull[Q, enums.Mosquitospecies](cols.Species),
Type: psql.Where[Q, enums.Signaltype](cols.Type),
SiteID: psql.WhereNull[Q, int32](cols.SiteID),
Location: psql.Where[Q, string](cols.Location),
LocationType: psql.WhereNull[Q, string](cols.LocationType),
FeaturePoolFeatureID: psql.WhereNull[Q, int32](cols.FeaturePoolFeatureID),
ReportID: psql.WhereNull[Q, int32](cols.ReportID),
}
}
@ -938,6 +1109,18 @@ func (o *Signal) Preload(name string, retrieved any) error {
rel.R.CreatorSignals = SignalSlice{o}
}
return nil
case "FeaturePoolFeatureFeaturePool":
rel, ok := retrieved.(*FeaturePool)
if !ok {
return fmt.Errorf("signal cannot load %T as %q", retrieved, name)
}
o.R.FeaturePoolFeatureFeaturePool = rel
if rel != nil {
rel.R.FeaturePoolFeatureSignals = SignalSlice{o}
}
return nil
case "Organization":
rel, ok := retrieved.(*Organization)
if !ok {
@ -946,6 +1129,18 @@ func (o *Signal) Preload(name string, retrieved any) error {
o.R.Organization = rel
if rel != nil {
rel.R.Signals = SignalSlice{o}
}
return nil
case "Report":
rel, ok := retrieved.(*PublicreportReport)
if !ok {
return fmt.Errorf("signal cannot load %T as %q", retrieved, name)
}
o.R.Report = rel
if rel != nil {
rel.R.Signals = SignalSlice{o}
}
@ -968,10 +1163,12 @@ func (o *Signal) Preload(name string, retrieved any) error {
}
type signalPreloader struct {
AddressorUser func(...psql.PreloadOption) psql.Preloader
CreatorUser func(...psql.PreloadOption) psql.Preloader
Organization func(...psql.PreloadOption) psql.Preloader
Site func(...psql.PreloadOption) psql.Preloader
AddressorUser func(...psql.PreloadOption) psql.Preloader
CreatorUser func(...psql.PreloadOption) psql.Preloader
FeaturePoolFeatureFeaturePool func(...psql.PreloadOption) psql.Preloader
Organization func(...psql.PreloadOption) psql.Preloader
Report func(...psql.PreloadOption) psql.Preloader
Site func(...psql.PreloadOption) psql.Preloader
}
func buildSignalPreloader() signalPreloader {
@ -1002,6 +1199,19 @@ func buildSignalPreloader() signalPreloader {
},
}, Users.Columns.Names(), opts...)
},
FeaturePoolFeatureFeaturePool: func(opts ...psql.PreloadOption) psql.Preloader {
return psql.Preload[*FeaturePool, FeaturePoolSlice](psql.PreloadRel{
Name: "FeaturePoolFeatureFeaturePool",
Sides: []psql.PreloadSide{
{
From: Signals,
To: FeaturePools,
FromColumns: []string{"feature_pool_feature_id"},
ToColumns: []string{"feature_id"},
},
},
}, FeaturePools.Columns.Names(), opts...)
},
Organization: func(opts ...psql.PreloadOption) psql.Preloader {
return psql.Preload[*Organization, OrganizationSlice](psql.PreloadRel{
Name: "Organization",
@ -1015,6 +1225,19 @@ func buildSignalPreloader() signalPreloader {
},
}, Organizations.Columns.Names(), opts...)
},
Report: func(opts ...psql.PreloadOption) psql.Preloader {
return psql.Preload[*PublicreportReport, PublicreportReportSlice](psql.PreloadRel{
Name: "Report",
Sides: []psql.PreloadSide{
{
From: Signals,
To: PublicreportReports,
FromColumns: []string{"report_id"},
ToColumns: []string{"id"},
},
},
}, PublicreportReports.Columns.Names(), opts...)
},
Site: func(opts ...psql.PreloadOption) psql.Preloader {
return psql.Preload[*Site, SiteSlice](psql.PreloadRel{
Name: "Site",
@ -1032,10 +1255,12 @@ func buildSignalPreloader() signalPreloader {
}
type signalThenLoader[Q orm.Loadable] struct {
AddressorUser func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q]
CreatorUser func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q]
Organization func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q]
Site func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q]
AddressorUser func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q]
CreatorUser func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q]
FeaturePoolFeatureFeaturePool func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q]
Organization func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q]
Report func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q]
Site func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q]
}
func buildSignalThenLoader[Q orm.Loadable]() signalThenLoader[Q] {
@ -1045,9 +1270,15 @@ func buildSignalThenLoader[Q orm.Loadable]() signalThenLoader[Q] {
type CreatorUserLoadInterface interface {
LoadCreatorUser(context.Context, bob.Executor, ...bob.Mod[*dialect.SelectQuery]) error
}
type FeaturePoolFeatureFeaturePoolLoadInterface interface {
LoadFeaturePoolFeatureFeaturePool(context.Context, bob.Executor, ...bob.Mod[*dialect.SelectQuery]) error
}
type OrganizationLoadInterface interface {
LoadOrganization(context.Context, bob.Executor, ...bob.Mod[*dialect.SelectQuery]) error
}
type ReportLoadInterface interface {
LoadReport(context.Context, bob.Executor, ...bob.Mod[*dialect.SelectQuery]) error
}
type SiteLoadInterface interface {
LoadSite(context.Context, bob.Executor, ...bob.Mod[*dialect.SelectQuery]) error
}
@ -1065,12 +1296,24 @@ func buildSignalThenLoader[Q orm.Loadable]() signalThenLoader[Q] {
return retrieved.LoadCreatorUser(ctx, exec, mods...)
},
),
FeaturePoolFeatureFeaturePool: thenLoadBuilder[Q](
"FeaturePoolFeatureFeaturePool",
func(ctx context.Context, exec bob.Executor, retrieved FeaturePoolFeatureFeaturePoolLoadInterface, mods ...bob.Mod[*dialect.SelectQuery]) error {
return retrieved.LoadFeaturePoolFeatureFeaturePool(ctx, exec, mods...)
},
),
Organization: thenLoadBuilder[Q](
"Organization",
func(ctx context.Context, exec bob.Executor, retrieved OrganizationLoadInterface, mods ...bob.Mod[*dialect.SelectQuery]) error {
return retrieved.LoadOrganization(ctx, exec, mods...)
},
),
Report: thenLoadBuilder[Q](
"Report",
func(ctx context.Context, exec bob.Executor, retrieved ReportLoadInterface, mods ...bob.Mod[*dialect.SelectQuery]) error {
return retrieved.LoadReport(ctx, exec, mods...)
},
),
Site: thenLoadBuilder[Q](
"Site",
func(ctx context.Context, exec bob.Executor, retrieved SiteLoadInterface, mods ...bob.Mod[*dialect.SelectQuery]) error {
@ -1187,6 +1430,61 @@ func (os SignalSlice) LoadCreatorUser(ctx context.Context, exec bob.Executor, mo
return nil
}
// LoadFeaturePoolFeatureFeaturePool loads the signal's FeaturePoolFeatureFeaturePool into the .R struct
func (o *Signal) LoadFeaturePoolFeatureFeaturePool(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error {
if o == nil {
return nil
}
// Reset the relationship
o.R.FeaturePoolFeatureFeaturePool = nil
related, err := o.FeaturePoolFeatureFeaturePool(mods...).One(ctx, exec)
if err != nil {
return err
}
related.R.FeaturePoolFeatureSignals = SignalSlice{o}
o.R.FeaturePoolFeatureFeaturePool = related
return nil
}
// LoadFeaturePoolFeatureFeaturePool loads the signal's FeaturePoolFeatureFeaturePool into the .R struct
func (os SignalSlice) LoadFeaturePoolFeatureFeaturePool(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error {
if len(os) == 0 {
return nil
}
featurePools, err := os.FeaturePoolFeatureFeaturePool(mods...).All(ctx, exec)
if err != nil {
return err
}
for _, o := range os {
if o == nil {
continue
}
for _, rel := range featurePools {
if !o.FeaturePoolFeatureID.IsValue() {
continue
}
if !(o.FeaturePoolFeatureID.IsValue() && o.FeaturePoolFeatureID.MustGet() == rel.FeatureID) {
continue
}
rel.R.FeaturePoolFeatureSignals = append(rel.R.FeaturePoolFeatureSignals, o)
o.R.FeaturePoolFeatureFeaturePool = rel
break
}
}
return nil
}
// LoadOrganization loads the signal's Organization into the .R struct
func (o *Signal) LoadOrganization(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error {
if o == nil {
@ -1239,6 +1537,61 @@ func (os SignalSlice) LoadOrganization(ctx context.Context, exec bob.Executor, m
return nil
}
// LoadReport loads the signal's Report into the .R struct
func (o *Signal) LoadReport(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error {
if o == nil {
return nil
}
// Reset the relationship
o.R.Report = nil
related, err := o.Report(mods...).One(ctx, exec)
if err != nil {
return err
}
related.R.Signals = SignalSlice{o}
o.R.Report = related
return nil
}
// LoadReport loads the signal's Report into the .R struct
func (os SignalSlice) LoadReport(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error {
if len(os) == 0 {
return nil
}
publicreportReports, err := os.Report(mods...).All(ctx, exec)
if err != nil {
return err
}
for _, o := range os {
if o == nil {
continue
}
for _, rel := range publicreportReports {
if !o.ReportID.IsValue() {
continue
}
if !(o.ReportID.IsValue() && o.ReportID.MustGet() == rel.ID) {
continue
}
rel.R.Signals = append(rel.R.Signals, o)
o.R.Report = rel
break
}
}
return nil
}
// LoadSite loads the signal's Site into the .R struct
func (o *Signal) LoadSite(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error {
if o == nil {

View file

@ -6,12 +6,21 @@ import (
"fmt"
"time"
"github.com/Gleipnir-Technology/bob"
"github.com/Gleipnir-Technology/bob/dialect/psql"
"github.com/Gleipnir-Technology/bob/dialect/psql/sm"
"github.com/Gleipnir-Technology/nidus-sync/db"
"github.com/Gleipnir-Technology/nidus-sync/db/enums"
"github.com/Gleipnir-Technology/nidus-sync/db/models"
"github.com/Gleipnir-Technology/nidus-sync/platform/types"
//"github.com/rs/zerolog/log"
"github.com/stephenafamo/scan"
)
type Pool struct {
Condition string `db:"condition" json:"condition"`
ID int32 `db:"id" json:"-"`
}
type UploadPoolDetail struct {
CountExisting int
CountNew int
@ -149,3 +158,19 @@ func errorsByLine(ctx context.Context, file *models.FileuploadFile) ([]UploadPoo
}
return file_errors, errors_by_line, nil
}
func poolList(ctx context.Context, org_id int32, pool_ids []int32) ([]*Pool, error) {
pools, err := bob.All(ctx, db.PGInstance.BobDB, psql.Select(
sm.Columns(
"condition",
"feature_id AS id",
),
sm.From(psql.Quote("feature_pool")),
sm.Where(
models.FeaturePools.Columns.FeatureID.EQ(psql.Any(pool_ids)),
),
), scan.StructMapper[*Pool]())
if err != nil {
return nil, fmt.Errorf("query feature_pool: %w", err)
}
return pools, nil
}

View file

@ -3,29 +3,20 @@ package publicreport
import (
"context"
"fmt"
"time"
"github.com/Gleipnir-Technology/bob"
"github.com/Gleipnir-Technology/bob/dialect/psql"
"github.com/Gleipnir-Technology/bob/dialect/psql/sm"
"github.com/Gleipnir-Technology/nidus-sync/db"
"github.com/Gleipnir-Technology/nidus-sync/platform/types"
"github.com/rs/zerolog/log"
"github.com/stephenafamo/scan"
)
type LogEntry struct {
Created time.Time `db:"created" json:"created"`
ID int32 `db:"id" json:"-"`
Message string `db:"message" json:"message"`
ReportID int32 `db:"report_id" json:"-"`
Type string `db:"type_" json:"type"`
UserID *int32 `db:"user_id" json:"user_id"`
}
func logEntriesByReportID(ctx context.Context, report_ids []int32) (map[int32][]LogEntry, error) {
results := make(map[int32][]LogEntry, len(report_ids))
func logEntriesByReportID(ctx context.Context, report_ids []int32) (map[int32][]types.LogEntry, error) {
results := make(map[int32][]types.LogEntry, len(report_ids))
for _, report_id := range report_ids {
results[report_id] = make([]LogEntry, 0)
results[report_id] = make([]types.LogEntry, 0)
}
rows, err := bob.All(ctx, db.PGInstance.BobDB, psql.Select(
@ -48,7 +39,7 @@ func logEntriesByReportID(ctx context.Context, report_ids []int32) (map[int32][]
),
sm.Where(psql.Quote("l", "report_id").EQ(psql.Any(report_ids))),
sm.OrderBy(psql.Quote("l", "created")),
), scan.StructMapper[LogEntry]())
), scan.StructMapper[types.LogEntry]())
if err != nil {
return results, fmt.Errorf("query created: %w", err)
}

View file

@ -9,31 +9,13 @@ import (
"github.com/Gleipnir-Technology/bob/dialect/psql/sm"
//"github.com/Gleipnir-Technology/nidus-sync/config"
"github.com/Gleipnir-Technology/nidus-sync/db"
"github.com/Gleipnir-Technology/nidus-sync/platform/types"
//"github.com/google/uuid"
//"github.com/rs/zerolog/log"
"github.com/stephenafamo/scan"
)
type Nuisance struct {
AdditionalInfo string `db:"additional_info" json:"additional_info"`
Duration string `db:"duration" json:"duration"`
IsLocationBackyard bool `db:"is_location_backyard" json:"is_location_backyard"`
IsLocationFrontyard bool `db:"is_location_frontyard" json:"is_location_frontyard"`
IsLocationGarden bool `db:"is_location_garden" json:"is_location_garden"`
IsLocationOther bool `db:"is_location_other" json:"is_location_other"`
IsLocationPool bool `db:"is_location_pool" json:"is_location_pool"`
ReportID int32 `db:"report_id" json:"-"`
SourceContainer bool `db:"source_container" json:"source_container"`
SourceDescription string `db:"source_description" json:"source_description"`
SourceGutter bool `db:"source_gutter" json:"source_gutter"`
SourceStagnant bool `db:"source_stagnant" json:"source_stagnant"`
TODDay bool `db:"tod_day" json:"time_of_day_day"`
TODEarly bool `db:"tod_early" json:"time_of_day_early"`
TODEvening bool `db:"tod_evening" json:"time_of_day_evening"`
TODNight bool `db:"tod_night" json:"time_of_day_night"`
}
func nuisancesByReportID(ctx context.Context, report_ids []int32) (map[int32]*Nuisance, error) {
func nuisancesByReportID(ctx context.Context, report_ids []int32) (map[int32]*types.Nuisance, error) {
rows, err := bob.All(ctx, db.PGInstance.BobDB, psql.Select(
sm.Columns(
"additional_info",
@ -57,13 +39,13 @@ func nuisancesByReportID(ctx context.Context, report_ids []int32) (map[int32]*Nu
sm.Where(psql.Quote("report_id").EQ(
psql.Any(report_ids),
)),
), scan.StructMapper[Nuisance]())
), scan.StructMapper[types.Nuisance]())
if err != nil {
return nil, fmt.Errorf("query nuisance: %w", err)
}
results := make(map[int32]*Nuisance, len(rows))
results := make(map[int32]*types.Nuisance, len(rows))
for _, row := range rows {
results[row.ReportID] = &Nuisance{
results[row.ReportID] = &types.Nuisance{
AdditionalInfo: row.AdditionalInfo,
Duration: row.Duration,
IsLocationBackyard: row.IsLocationBackyard,

View file

@ -3,10 +3,10 @@ package publicreport
import (
"context"
"fmt"
"time"
"github.com/Gleipnir-Technology/bob"
"github.com/Gleipnir-Technology/bob/dialect/psql"
"github.com/Gleipnir-Technology/bob/dialect/psql/dialect"
"github.com/Gleipnir-Technology/bob/dialect/psql/sm"
//"github.com/Gleipnir-Technology/nidus-sync/config"
"github.com/Gleipnir-Technology/nidus-sync/db"
@ -17,47 +17,15 @@ import (
"github.com/stephenafamo/scan"
)
type Report struct {
Log []LogEntry `db:"-" json:"log"`
Address types.Address `db:"address" json:"address"`
AddressRaw string `db:"address_raw" json:"address_raw"`
Created time.Time `db:"created" json:"created"`
ID int32 `db:"id" json:"-"`
Images []types.Image `db:"images" json:"images"`
Location *types.Location `db:"location" json:"location"`
Nuisance *Nuisance `db:"nuisance" json:"nuisance"`
PublicID string `db:"public_id" json:"public_id"`
Reporter types.Contact `db:"reporter" json:"reporter"`
Status string `db:"status" json:"status"`
Type string `db:"report_type" json:"type"`
Water *Water `db:"water" json:"water"`
}
func ReportsForOrganization(ctx context.Context, org_id int32) ([]*Report, error) {
rows, err := bob.All(ctx, db.PGInstance.BobDB, psql.Select(
sm.Columns(
"address_country AS \"address.country\"",
"address_locality AS \"address.locality\"",
"address_number AS \"address.number\"",
"address_postal_code AS \"address.postal_code\"",
"address_raw AS address_raw",
"address_region AS \"address.region\"",
"address_street AS \"address.street\"",
"created",
"id",
"COALESCE(ST_Y(location::geometry::geometry(point, 4326)), 0.0) AS \"location.latitude\"",
"COALESCE(ST_X(location::geometry::geometry(point, 4326)), 0.0) AS \"location.longitude\"",
"public_id",
"report_type",
"reporter_email AS \"reporter.email\"",
"reporter_name AS \"reporter.name\"",
"reporter_phone AS \"reporter.phone\"",
"status",
),
sm.From("publicreport.report"),
sm.Where(psql.Quote("publicreport", "report", "organization_id").EQ(psql.Arg(org_id))),
func ReportsForOrganization(ctx context.Context, org_id int32) ([]*types.Report, error) {
query := reportQuery(org_id)
query.Apply(
sm.Where(psql.Quote("publicreport", "report", "reviewed").IsNull()),
), scan.StructMapper[Report]())
)
return reportQueryToRows(ctx, org_id, query)
}
func reportQueryToRows(ctx context.Context, org_id int32, query bob.BaseQuery[*dialect.SelectQuery]) ([]*types.Report, error) {
rows, err := bob.All(ctx, db.PGInstance.BobDB, query, scan.StructMapper[types.Report]())
if err != nil {
return nil, fmt.Errorf("get reports: %w", err)
@ -83,7 +51,7 @@ func ReportsForOrganization(ctx context.Context, org_id int32) ([]*Report, error
return nil, fmt.Errorf("waters: %w", err)
}
results := make([]*Report, len(rows))
results := make([]*types.Report, len(rows))
for i, row := range rows {
images, ok := images_by_id[row.ID]
if ok {
@ -101,6 +69,13 @@ func ReportsForOrganization(ctx context.Context, org_id int32) ([]*Report, error
}
return results, nil
}
func Reports(ctx context.Context, org_id int32, ids []int32) ([]*types.Report, error) {
query := reportQuery(org_id)
query.Apply(
sm.Where(psql.Quote("publicreport", "report", "reviewed").IsNull()),
)
return reportQueryToRows(ctx, org_id, query)
}
func ReportsForOrganizationCount(ctx context.Context, org_id int32) (uint, error) {
type _Row struct {
Count uint `db:"count"`
@ -117,3 +92,28 @@ func ReportsForOrganizationCount(ctx context.Context, org_id int32) (uint, error
}
return row.Count, nil
}
func reportQuery(org_id int32) bob.BaseQuery[*dialect.SelectQuery] {
return psql.Select(
sm.Columns(
"address_country AS \"address.country\"",
"address_locality AS \"address.locality\"",
"address_number AS \"address.number\"",
"address_postal_code AS \"address.postal_code\"",
"address_raw AS address_raw",
"address_region AS \"address.region\"",
"address_street AS \"address.street\"",
"created",
"id",
"COALESCE(ST_Y(location::geometry::geometry(point, 4326)), 0.0) AS \"location.latitude\"",
"COALESCE(ST_X(location::geometry::geometry(point, 4326)), 0.0) AS \"location.longitude\"",
"public_id",
"report_type",
"reporter_email AS \"reporter.email\"",
"reporter_name AS \"reporter.name\"",
"reporter_phone AS \"reporter.phone\"",
"status",
),
sm.From("publicreport.report"),
sm.Where(psql.Quote("publicreport", "report", "organization_id").EQ(psql.Arg(org_id))),
)
}

View file

@ -16,25 +16,7 @@ import (
"github.com/stephenafamo/scan"
)
type Water struct {
AccessComments string `db:"access_comments" json:"access_comments"`
AccessGate bool `db:"access_gate" json:"access_gate"`
AccessFence bool `db:"access_fence" json:"access_fence"`
AccessLocked bool `db:"access_locked" json:"access_locked"`
AccessDog bool `db:"access_dog" json:"access_dog"`
AccessOther bool `db:"access_other" json:"access_other"`
Comments string `db:"comments" json:"comments"`
HasAdult bool `db:"has_adult" json:"has_adult"`
HasBackyardPermission bool `db:"has_backyard_permission" json:"has_backyard_permission"`
HasLarvae bool `db:"has_larvae" json:"has_larvae"`
HasPupae bool `db:"has_pupae" json:"has_pupae"`
IsReporterConfidential bool `db:"is_reporter_confidential" json:"is_reporter_confidential"`
IsReporterOwner bool `db:"is_reporter_owner" json:"is_reporter_owner"`
Owner types.Contact `db:"owner" json:"owner"`
ReportID int32 `db:"report_id" json:"-"`
}
func watersByReportID(ctx context.Context, report_ids []int32) (map[int32]*Water, error) {
func watersByReportID(ctx context.Context, report_ids []int32) (map[int32]*types.Water, error) {
rows, err := bob.All(ctx, db.PGInstance.BobDB, psql.Select(
sm.Columns(
"access_comments",
@ -59,13 +41,13 @@ func watersByReportID(ctx context.Context, report_ids []int32) (map[int32]*Water
sm.Where(psql.Quote("report_id").EQ(
psql.Any(report_ids),
)),
), scan.StructMapper[Water]())
), scan.StructMapper[types.Water]())
if err != nil {
return nil, fmt.Errorf("query water: %w", err)
}
results := make(map[int32]*Water, len(rows))
results := make(map[int32]*types.Water, len(rows))
for _, row := range rows {
results[row.ReportID] = &Water{
results[row.ReportID] = &types.Water{
AccessComments: row.AccessComments,
AccessGate: row.AccessGate,
AccessFence: row.AccessFence,

View file

@ -141,14 +141,15 @@ func commitReviewPool(ctx context.Context, txn bob.Tx, user User, review_task_po
return nhttp.NewError("find feature %d: %w", feature_pool.FeatureID, err)
}
signal, err := models.Signals.Insert(&models.SignalSetter{
Addressed: omitnull.FromPtr[time.Time](nil),
Addressor: omitnull.FromPtr[int32](nil),
Created: omit.From(time.Now()),
Creator: omit.From[int32](int32(user.ID)),
Addressed: omitnull.FromPtr[time.Time](nil),
Addressor: omitnull.FromPtr[int32](nil),
Created: omit.From(time.Now()),
Creator: omit.From[int32](int32(user.ID)),
FeaturePoolFeatureID: omitnull.From(feature_pool.FeatureID),
//ID: omit.Val[int32],
OrganizationID: omit.From(user.Organization.ID()),
ReportID: omitnull.FromPtr[int32](nil),
Species: omitnull.FromPtr[enums.Mosquitospecies](nil),
Title: omit.From[string](""),
Type: omit.From(enums.SignaltypeFlyoverPool),
SiteID: omitnull.From(feature.SiteID),
Location: omit.From[string](feature.Location.GetOr("")),

View file

@ -15,6 +15,7 @@ import (
"github.com/Gleipnir-Technology/nidus-sync/db/enums"
"github.com/Gleipnir-Technology/nidus-sync/db/models"
"github.com/Gleipnir-Technology/nidus-sync/platform/event"
"github.com/Gleipnir-Technology/nidus-sync/platform/publicreport"
"github.com/Gleipnir-Technology/nidus-sync/platform/types"
//"github.com/Gleipnir-Technology/nidus-sync/platform/geocode"
//"github.com/Gleipnir-Technology/nidus-sync/platform/geom"
@ -32,8 +33,9 @@ type Signal struct {
Creator int32 `db:"creator" json:"creator"`
ID int32 `db:"id" json:"id"`
Location types.Location `db:"location" json:"location"`
Pool *Pool `db:"pool" json:"pool"`
Report *types.Report `db:"report" json:"report"`
Species *string `db:"species" json:"species"`
Title string `db:"title" json:"title"`
Type string `db:"type" json:"type"`
}
@ -115,16 +117,17 @@ func SignalCreateFromPublicreport(ctx context.Context, user User, report_id stri
}
log.Debug().Str("location", location).Msg("inserting signal")
signal, err := models.Signals.Insert(&models.SignalSetter{
Addressed: omitnull.FromPtr[time.Time](nil),
Addressor: omitnull.FromPtr[int32](nil),
Created: omit.From(time.Now()),
Creator: omit.From(int32(user.ID)),
Addressed: omitnull.FromPtr[time.Time](nil),
Addressor: omitnull.FromPtr[int32](nil),
Created: omit.From(time.Now()),
Creator: omit.From(int32(user.ID)),
FeaturePoolFeatureID: omitnull.FromPtr[int32](nil),
// ID
OrganizationID: omit.From(int32(user.Organization.ID())),
Location: omit.From(location),
ReportID: omitnull.From(report.ID),
Species: omitnull.FromPtr[enums.Mosquitospecies](nil),
SiteID: omitnull.From(site_id),
Title: omit.From[string](""),
Type: omit.From[enums.Signaltype](signal_type),
}).One(ctx, txn)
if err != nil {
@ -146,7 +149,8 @@ func SignalCreateFromPublicreport(ctx context.Context, user User, report_id stri
return &signal.ID, nil
}
func SignalList(ctx context.Context, user User, limit int) ([]Signal, error) {
func SignalList(ctx context.Context, user User, limit int) ([]*Signal, error) {
org_id := user.Organization.ID()
rows, err := bob.All(ctx, db.PGInstance.BobDB, psql.Select(
sm.Columns(
"signal.addressed AS addressed",
@ -154,8 +158,9 @@ func SignalList(ctx context.Context, user User, limit int) ([]Signal, error) {
"signal.created AS created",
"signal.creator AS creator",
"signal.id AS id",
"COALESCE(signal.feature_pool_feature_id, 0) AS \"pool.id\"",
"COALESCE(signal.report_id, 0) AS \"report.id\"",
"signal.species AS species",
"signal.title AS title",
"signal.type_ AS type",
"address.country AS \"address.country\"",
"address.locality AS \"address.locality\"",
@ -164,8 +169,9 @@ func SignalList(ctx context.Context, user User, limit int) ([]Signal, error) {
"address.region AS \"address.region\"",
"address.street AS \"address.street\"",
"address.unit AS \"address.unit\"",
"ST_Y(address.location) AS \"location.latitude\"",
"ST_X(address.location) AS \"location.longitude\"",
// This will work great, up until we add polygons to signal
"ST_Y(signal.location) AS \"location.latitude\"",
"ST_X(signal.location) AS \"location.longitude\"",
),
sm.From("signal"),
sm.LeftJoin("site").OnEQ(
@ -176,13 +182,55 @@ func SignalList(ctx context.Context, user User, limit int) ([]Signal, error) {
psql.Quote("site", "address_id"),
psql.Quote("address", "id"),
),
sm.Where(psql.Quote("signal", "organization_id").EQ(psql.Arg(user.Organization.ID()))),
sm.Where(psql.Quote("signal", "organization_id").EQ(psql.Arg(org_id))),
sm.Where(psql.Quote("signal", "addressed").IsNull()),
sm.Limit(limit),
), scan.StructMapper[Signal]())
), scan.StructMapper[*Signal]())
log.Debug().Int("len", len(rows)).Msg("got signals")
if err != nil {
return nil, fmt.Errorf("failed to get signals: %w", err)
}
report_ids := make([]int32, 0)
pool_ids := make([]int32, 0)
for _, row := range rows {
if row.Report.ID != 0 {
report_ids = append(report_ids, row.Report.ID)
} else if row.Pool.ID != 0 {
pool_ids = append(pool_ids, row.Pool.ID)
}
}
pools, err := poolList(ctx, org_id, pool_ids)
if err != nil {
return nil, fmt.Errorf("getting pools by ID: %w", err)
}
reports, err := publicreport.Reports(ctx, org_id, report_ids)
if err != nil {
return nil, fmt.Errorf("getting reports by ID: %w", err)
}
pool_map := make(map[int32]*Pool, len(pools))
for _, pool := range pools {
pool_map[pool.ID] = pool
log.Debug().Int32("pool", pool.ID).Msg("Added to map")
}
report_map := make(map[int32]*types.Report, len(report_ids))
for _, report := range reports {
report_map[report.ID] = report
}
for _, row := range rows {
if row.Pool.ID != 0 {
p, ok := pool_map[row.Pool.ID]
if !ok {
return nil, fmt.Errorf("failed to get pool %d for %d", row.Pool.ID, row.ID)
}
if p == nil {
return nil, fmt.Errorf("got nil pool from %d for %d", row.Pool.ID, row.ID)
}
row.Pool = p
row.Report = nil
} else if row.Report.ID != 0 {
row.Pool = nil
row.Report = report_map[row.Report.ID]
}
}
return rows, nil
}

View file

@ -0,0 +1,14 @@
package types
import (
"time"
)
type LogEntry struct {
Created time.Time `db:"created" json:"created"`
ID int32 `db:"id" json:"-"`
Message string `db:"message" json:"message"`
ReportID int32 `db:"report_id" json:"-"`
Type string `db:"type_" json:"type"`
UserID *int32 `db:"user_id" json:"user_id"`
}

View file

@ -0,0 +1,20 @@
package types
type Nuisance struct {
AdditionalInfo string `db:"additional_info" json:"additional_info"`
Duration string `db:"duration" json:"duration"`
IsLocationBackyard bool `db:"is_location_backyard" json:"is_location_backyard"`
IsLocationFrontyard bool `db:"is_location_frontyard" json:"is_location_frontyard"`
IsLocationGarden bool `db:"is_location_garden" json:"is_location_garden"`
IsLocationOther bool `db:"is_location_other" json:"is_location_other"`
IsLocationPool bool `db:"is_location_pool" json:"is_location_pool"`
ReportID int32 `db:"report_id" json:"-"`
SourceContainer bool `db:"source_container" json:"source_container"`
SourceDescription string `db:"source_description" json:"source_description"`
SourceGutter bool `db:"source_gutter" json:"source_gutter"`
SourceStagnant bool `db:"source_stagnant" json:"source_stagnant"`
TODDay bool `db:"tod_day" json:"time_of_day_day"`
TODEarly bool `db:"tod_early" json:"time_of_day_early"`
TODEvening bool `db:"tod_evening" json:"time_of_day_evening"`
TODNight bool `db:"tod_night" json:"time_of_day_night"`
}

21
platform/types/report.go Normal file
View file

@ -0,0 +1,21 @@
package types
import (
"time"
)
type Report struct {
Log []LogEntry `db:"-" json:"log"`
Address Address `db:"address" json:"address"`
AddressRaw string `db:"address_raw" json:"address_raw"`
Created time.Time `db:"created" json:"created"`
ID int32 `db:"id" json:"-"`
Images []Image `db:"images" json:"images"`
Location *Location `db:"location" json:"location"`
Nuisance *Nuisance `db:"nuisance" json:"nuisance"`
PublicID string `db:"public_id" json:"public_id"`
Reporter Contact `db:"reporter" json:"reporter"`
Status string `db:"status" json:"status"`
Type string `db:"report_type" json:"type"`
Water *Water `db:"water" json:"water"`
}

19
platform/types/water.go Normal file
View file

@ -0,0 +1,19 @@
package types
type Water struct {
AccessComments string `db:"access_comments" json:"access_comments"`
AccessGate bool `db:"access_gate" json:"access_gate"`
AccessFence bool `db:"access_fence" json:"access_fence"`
AccessLocked bool `db:"access_locked" json:"access_locked"`
AccessDog bool `db:"access_dog" json:"access_dog"`
AccessOther bool `db:"access_other" json:"access_other"`
Comments string `db:"comments" json:"comments"`
HasAdult bool `db:"has_adult" json:"has_adult"`
HasBackyardPermission bool `db:"has_backyard_permission" json:"has_backyard_permission"`
HasLarvae bool `db:"has_larvae" json:"has_larvae"`
HasPupae bool `db:"has_pupae" json:"has_pupae"`
IsReporterConfidential bool `db:"is_reporter_confidential" json:"is_reporter_confidential"`
IsReporterOwner bool `db:"is_reporter_owner" json:"is_reporter_owner"`
Owner Contact `db:"owner" json:"owner"`
ReportID int32 `db:"report_id" json:"-"`
}