From 1a9a72adc065af7ff6b3bccaabacc5168a4fd967 Mon Sep 17 00:00:00 2001 From: Eli Ribble Date: Sat, 14 Mar 2026 15:53:16 +0000 Subject: [PATCH] Create district catch-all, make organization on public reports not null --- db/dbinfo/organization.bob.go | 32 +++++++++++- db/dbinfo/publicreport.nuisance.bob.go | 4 +- db/dbinfo/publicreport.water.bob.go | 4 +- db/migrations/00108_organization_catchall.sql | 16 ++++++ db/models/organization.bob.go | 51 +++++++++++++------ db/models/publicreport.nuisance.bob.go | 29 +++++------ db/models/publicreport.water.bob.go | 29 +++++------ platform/district.go | 21 ++++++-- platform/nuisance.go | 2 +- platform/water.go | 2 +- rmo/status.go | 25 ++++----- 11 files changed, 140 insertions(+), 75 deletions(-) create mode 100644 db/migrations/00108_organization_catchall.sql diff --git a/db/dbinfo/organization.bob.go b/db/dbinfo/organization.bob.go index 68f13775..1619bef3 100644 --- a/db/dbinfo/organization.bob.go +++ b/db/dbinfo/organization.bob.go @@ -312,6 +312,15 @@ var Organizations = Table[ Generated: false, AutoIncr: false, }, + IsCatchall: column{ + Name: "is_catchall", + DBType: "boolean", + Default: "", + Comment: "", + Nullable: false, + Generated: false, + AutoIncr: false, + }, }, Indexes: organizationIndexes{ OrganizationPkey: index{ @@ -331,6 +340,23 @@ var Organizations = Table[ Where: "", Include: []string{}, }, + OnlyOneCatchall: index{ + Type: "btree", + Name: "only_one_catchall", + Columns: []indexColumn{ + { + Name: "is_catchall", + Desc: null.FromCond(false, true), + IsExpression: false, + }, + }, + Unique: true, + Comment: "", + NullsFirst: []bool{false}, + NullsDistinct: false, + Where: "(is_catchall = true)", + Include: []string{}, + }, OrganizationImportDistrictGidKey: index{ Type: "btree", Name: "organization_import_district_gid_key", @@ -459,23 +485,25 @@ type organizationColumns struct { ArcgisAccountID column FieldseekerServiceFeatureItemID column ArcgisMapServiceID column + IsCatchall column } func (c organizationColumns) AsSlice() []column { return []column{ - c.ID, c.Name, c.ImportDistrictGid, c.Website, c.LogoUUID, c.Slug, c.GeneralManagerName, c.MailingAddressCity, c.MailingAddressPostalCode, c.MailingAddressStreet, c.OfficeAddressCity, c.OfficeAddressPostalCode, c.OfficeAddressStreet, c.ServiceAreaGeometry, c.ServiceAreaSquareMeters, c.ServiceAreaCentroid, c.ServiceAreaExtent, c.OfficeFax, c.OfficePhone, c.ServiceAreaXmin, c.ServiceAreaYmin, c.ServiceAreaXmax, c.ServiceAreaYmax, c.ServiceAreaCentroidGeojson, c.ServiceAreaCentroidX, c.ServiceAreaCentroidY, c.MailingAddressCountry, c.MailingAddressState, c.OfficeAddressCountry, c.OfficeAddressState, c.ArcgisAccountID, c.FieldseekerServiceFeatureItemID, c.ArcgisMapServiceID, + c.ID, c.Name, c.ImportDistrictGid, c.Website, c.LogoUUID, c.Slug, c.GeneralManagerName, c.MailingAddressCity, c.MailingAddressPostalCode, c.MailingAddressStreet, c.OfficeAddressCity, c.OfficeAddressPostalCode, c.OfficeAddressStreet, c.ServiceAreaGeometry, c.ServiceAreaSquareMeters, c.ServiceAreaCentroid, c.ServiceAreaExtent, c.OfficeFax, c.OfficePhone, c.ServiceAreaXmin, c.ServiceAreaYmin, c.ServiceAreaXmax, c.ServiceAreaYmax, c.ServiceAreaCentroidGeojson, c.ServiceAreaCentroidX, c.ServiceAreaCentroidY, c.MailingAddressCountry, c.MailingAddressState, c.OfficeAddressCountry, c.OfficeAddressState, c.ArcgisAccountID, c.FieldseekerServiceFeatureItemID, c.ArcgisMapServiceID, c.IsCatchall, } } type organizationIndexes struct { OrganizationPkey index + OnlyOneCatchall index OrganizationImportDistrictGidKey index OrganizationSlugKey index } func (i organizationIndexes) AsSlice() []index { return []index{ - i.OrganizationPkey, i.OrganizationImportDistrictGidKey, i.OrganizationSlugKey, + i.OrganizationPkey, i.OnlyOneCatchall, i.OrganizationImportDistrictGidKey, i.OrganizationSlugKey, } } diff --git a/db/dbinfo/publicreport.nuisance.bob.go b/db/dbinfo/publicreport.nuisance.bob.go index e2529b09..9e991750 100644 --- a/db/dbinfo/publicreport.nuisance.bob.go +++ b/db/dbinfo/publicreport.nuisance.bob.go @@ -135,9 +135,9 @@ var PublicreportNuisances = Table[ OrganizationID: column{ Name: "organization_id", DBType: "integer", - Default: "NULL", + Default: "", Comment: "", - Nullable: true, + Nullable: false, Generated: false, AutoIncr: false, }, diff --git a/db/dbinfo/publicreport.water.bob.go b/db/dbinfo/publicreport.water.bob.go index 2814c7c1..cd707a67 100644 --- a/db/dbinfo/publicreport.water.bob.go +++ b/db/dbinfo/publicreport.water.bob.go @@ -270,9 +270,9 @@ var PublicreportWaters = Table[ OrganizationID: column{ Name: "organization_id", DBType: "integer", - Default: "NULL", + Default: "", Comment: "", - Nullable: true, + Nullable: false, Generated: false, AutoIncr: false, }, diff --git a/db/migrations/00108_organization_catchall.sql b/db/migrations/00108_organization_catchall.sql new file mode 100644 index 00000000..11ed3693 --- /dev/null +++ b/db/migrations/00108_organization_catchall.sql @@ -0,0 +1,16 @@ +-- +goose Up +ALTER TABLE organization ADD COLUMN is_catchall BOOLEAN; +UPDATE organization SET is_catchall = false; +ALTER TABLE organization ALTER COLUMN is_catchall SET NOT NULL; +CREATE UNIQUE INDEX only_one_catchall +ON organization (is_catchall) +WHERE is_catchall = true; +INSERT INTO organization(name, is_catchall) VALUES ('Gleipnir Catch-All', true); +UPDATE publicreport.nuisance SET organization_id = organization.id FROM organization WHERE organization.is_catchall = true; +ALTER TABLE publicreport.nuisance ALTER COLUMN organization_id SET NOT NULL; +UPDATE publicreport.water SET organization_id = organization.id FROM organization WHERE organization.is_catchall = true; +ALTER TABLE publicreport.water ALTER COLUMN organization_id SET NOT NULL; +-- +goose Down +ALTER TABLE organization DROP COLUMN is_catchall; +ALTER TABLE publicreport.nuisance ALTER COLUMN organization_id DROP NOT NULL; +ALTER TABLE publicreport.water ALTER COLUMN organization_id DROP NOT NULL; diff --git a/db/models/organization.bob.go b/db/models/organization.bob.go index 2526d152..f7acc96c 100644 --- a/db/models/organization.bob.go +++ b/db/models/organization.bob.go @@ -60,6 +60,7 @@ type Organization struct { ArcgisAccountID null.Val[string] `db:"arcgis_account_id" ` FieldseekerServiceFeatureItemID null.Val[string] `db:"fieldseeker_service_feature_item_id" ` ArcgisMapServiceID null.Val[string] `db:"arcgis_map_service_id" ` + IsCatchall bool `db:"is_catchall" ` R organizationR `db:"-" ` } @@ -128,7 +129,7 @@ type organizationR struct { func buildOrganizationColumns(alias string) organizationColumns { return organizationColumns{ ColumnsExpr: expr.NewColumnsExpr( - "id", "name", "import_district_gid", "website", "logo_uuid", "slug", "general_manager_name", "mailing_address_city", "mailing_address_postal_code", "mailing_address_street", "office_address_city", "office_address_postal_code", "office_address_street", "service_area_geometry", "service_area_square_meters", "service_area_centroid", "service_area_extent", "office_fax", "office_phone", "service_area_xmin", "service_area_ymin", "service_area_xmax", "service_area_ymax", "service_area_centroid_geojson", "service_area_centroid_x", "service_area_centroid_y", "mailing_address_country", "mailing_address_state", "office_address_country", "office_address_state", "arcgis_account_id", "fieldseeker_service_feature_item_id", "arcgis_map_service_id", + "id", "name", "import_district_gid", "website", "logo_uuid", "slug", "general_manager_name", "mailing_address_city", "mailing_address_postal_code", "mailing_address_street", "office_address_city", "office_address_postal_code", "office_address_street", "service_area_geometry", "service_area_square_meters", "service_area_centroid", "service_area_extent", "office_fax", "office_phone", "service_area_xmin", "service_area_ymin", "service_area_xmax", "service_area_ymax", "service_area_centroid_geojson", "service_area_centroid_x", "service_area_centroid_y", "mailing_address_country", "mailing_address_state", "office_address_country", "office_address_state", "arcgis_account_id", "fieldseeker_service_feature_item_id", "arcgis_map_service_id", "is_catchall", ).WithParent("organization"), tableAlias: alias, ID: psql.Quote(alias, "id"), @@ -164,6 +165,7 @@ func buildOrganizationColumns(alias string) organizationColumns { ArcgisAccountID: psql.Quote(alias, "arcgis_account_id"), FieldseekerServiceFeatureItemID: psql.Quote(alias, "fieldseeker_service_feature_item_id"), ArcgisMapServiceID: psql.Quote(alias, "arcgis_map_service_id"), + IsCatchall: psql.Quote(alias, "is_catchall"), } } @@ -203,6 +205,7 @@ type organizationColumns struct { ArcgisAccountID psql.Expression FieldseekerServiceFeatureItemID psql.Expression ArcgisMapServiceID psql.Expression + IsCatchall psql.Expression } func (c organizationColumns) Alias() string { @@ -240,10 +243,11 @@ type OrganizationSetter struct { ArcgisAccountID omitnull.Val[string] `db:"arcgis_account_id" ` FieldseekerServiceFeatureItemID omitnull.Val[string] `db:"fieldseeker_service_feature_item_id" ` ArcgisMapServiceID omitnull.Val[string] `db:"arcgis_map_service_id" ` + IsCatchall omit.Val[bool] `db:"is_catchall" ` } func (s OrganizationSetter) SetColumns() []string { - vals := make([]string, 0, 23) + vals := make([]string, 0, 24) if s.ID.IsValue() { vals = append(vals, "id") } @@ -313,6 +317,9 @@ func (s OrganizationSetter) SetColumns() []string { if !s.ArcgisMapServiceID.IsUnset() { vals = append(vals, "arcgis_map_service_id") } + if s.IsCatchall.IsValue() { + vals = append(vals, "is_catchall") + } return vals } @@ -386,6 +393,9 @@ func (s OrganizationSetter) Overwrite(t *Organization) { if !s.ArcgisMapServiceID.IsUnset() { t.ArcgisMapServiceID = s.ArcgisMapServiceID.MustGetNull() } + if s.IsCatchall.IsValue() { + t.IsCatchall = s.IsCatchall.MustGet() + } } func (s *OrganizationSetter) Apply(q *dialect.InsertQuery) { @@ -394,7 +404,7 @@ func (s *OrganizationSetter) 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, 23) + vals := make([]bob.Expression, 24) if s.ID.IsValue() { vals[0] = psql.Arg(s.ID.MustGet()) } else { @@ -533,6 +543,12 @@ func (s *OrganizationSetter) Apply(q *dialect.InsertQuery) { vals[22] = psql.Raw("DEFAULT") } + if s.IsCatchall.IsValue() { + vals[23] = psql.Arg(s.IsCatchall.MustGet()) + } else { + vals[23] = psql.Raw("DEFAULT") + } + return bob.ExpressSlice(ctx, w, d, start, vals, "", ", ", "") })) } @@ -542,7 +558,7 @@ func (s OrganizationSetter) UpdateMod() bob.Mod[*dialect.UpdateQuery] { } func (s OrganizationSetter) Expressions(prefix ...string) []bob.Expression { - exprs := make([]bob.Expression, 0, 23) + exprs := make([]bob.Expression, 0, 24) if s.ID.IsValue() { exprs = append(exprs, expr.Join{Sep: " = ", Exprs: []bob.Expression{ @@ -705,6 +721,13 @@ func (s OrganizationSetter) Expressions(prefix ...string) []bob.Expression { }}) } + if s.IsCatchall.IsValue() { + exprs = append(exprs, expr.Join{Sep: " = ", Exprs: []bob.Expression{ + psql.Quote(append(prefix, "is_catchall")...), + psql.Arg(s.IsCatchall), + }}) + } + return exprs } @@ -4861,7 +4884,7 @@ func (organization0 *Organization) AttachFieldseekerServiceFeatureItemServiceFea func insertOrganizationNuisances0(ctx context.Context, exec bob.Executor, publicreportNuisances1 []*PublicreportNuisanceSetter, organization0 *Organization) (PublicreportNuisanceSlice, error) { for i := range publicreportNuisances1 { - publicreportNuisances1[i].OrganizationID = omitnull.From(organization0.ID) + publicreportNuisances1[i].OrganizationID = omit.From(organization0.ID) } ret, err := PublicreportNuisances.Insert(bob.ToMods(publicreportNuisances1...)).All(ctx, exec) @@ -4874,7 +4897,7 @@ func insertOrganizationNuisances0(ctx context.Context, exec bob.Executor, public func attachOrganizationNuisances0(ctx context.Context, exec bob.Executor, count int, publicreportNuisances1 PublicreportNuisanceSlice, organization0 *Organization) (PublicreportNuisanceSlice, error) { setter := &PublicreportNuisanceSetter{ - OrganizationID: omitnull.From(organization0.ID), + OrganizationID: omit.From(organization0.ID), } err := publicreportNuisances1.UpdateAll(ctx, exec, *setter) @@ -4929,7 +4952,7 @@ func (organization0 *Organization) AttachNuisances(ctx context.Context, exec bob func insertOrganizationWaters0(ctx context.Context, exec bob.Executor, publicreportWaters1 []*PublicreportWaterSetter, organization0 *Organization) (PublicreportWaterSlice, error) { for i := range publicreportWaters1 { - publicreportWaters1[i].OrganizationID = omitnull.From(organization0.ID) + publicreportWaters1[i].OrganizationID = omit.From(organization0.ID) } ret, err := PublicreportWaters.Insert(bob.ToMods(publicreportWaters1...)).All(ctx, exec) @@ -4942,7 +4965,7 @@ func insertOrganizationWaters0(ctx context.Context, exec bob.Executor, publicrep func attachOrganizationWaters0(ctx context.Context, exec bob.Executor, count int, publicreportWaters1 PublicreportWaterSlice, organization0 *Organization) (PublicreportWaterSlice, error) { setter := &PublicreportWaterSetter{ - OrganizationID: omitnull.From(organization0.ID), + OrganizationID: omit.From(organization0.ID), } err := publicreportWaters1.UpdateAll(ctx, exec, *setter) @@ -5233,6 +5256,7 @@ type organizationWhere[Q psql.Filterable] struct { ArcgisAccountID psql.WhereNullMod[Q, string] FieldseekerServiceFeatureItemID psql.WhereNullMod[Q, string] ArcgisMapServiceID psql.WhereNullMod[Q, string] + IsCatchall psql.WhereMod[Q, bool] } func (organizationWhere[Q]) AliasedAs(alias string) organizationWhere[Q] { @@ -5274,6 +5298,7 @@ func buildOrganizationWhere[Q psql.Filterable](cols organizationColumns) organiz ArcgisAccountID: psql.WhereNull[Q, string](cols.ArcgisAccountID), FieldseekerServiceFeatureItemID: psql.WhereNull[Q, string](cols.FieldseekerServiceFeatureItemID), ArcgisMapServiceID: psql.WhereNull[Q, string](cols.ArcgisMapServiceID), + IsCatchall: psql.Where[Q, bool](cols.IsCatchall), } } @@ -9101,10 +9126,7 @@ func (os OrganizationSlice) LoadNuisances(ctx context.Context, exec bob.Executor for _, rel := range publicreportNuisances { - if !rel.OrganizationID.IsValue() { - continue - } - if !(rel.OrganizationID.IsValue() && o.ID == rel.OrganizationID.MustGet()) { + if !(o.ID == rel.OrganizationID) { continue } @@ -9165,10 +9187,7 @@ func (os OrganizationSlice) LoadWaters(ctx context.Context, exec bob.Executor, m for _, rel := range publicreportWaters { - if !rel.OrganizationID.IsValue() { - continue - } - if !(rel.OrganizationID.IsValue() && o.ID == rel.OrganizationID.MustGet()) { + if !(o.ID == rel.OrganizationID) { continue } diff --git a/db/models/publicreport.nuisance.bob.go b/db/models/publicreport.nuisance.bob.go index 1144f655..9a3daa9e 100644 --- a/db/models/publicreport.nuisance.bob.go +++ b/db/models/publicreport.nuisance.bob.go @@ -40,7 +40,7 @@ type PublicreportNuisance struct { ReporterPhone null.Val[string] `db:"reporter_phone" ` AddressRaw string `db:"address_raw" ` Status enums.PublicreportReportstatustype `db:"status" ` - OrganizationID null.Val[int32] `db:"organization_id" ` + OrganizationID int32 `db:"organization_id" ` SourceGutter bool `db:"source_gutter" ` H3cell null.Val[string] `db:"h3cell" ` AddressCountry string `db:"address_country" ` @@ -207,7 +207,7 @@ type PublicreportNuisanceSetter struct { ReporterPhone omitnull.Val[string] `db:"reporter_phone" ` AddressRaw omit.Val[string] `db:"address_raw" ` Status omit.Val[enums.PublicreportReportstatustype] `db:"status" ` - OrganizationID omitnull.Val[int32] `db:"organization_id" ` + OrganizationID omit.Val[int32] `db:"organization_id" ` SourceGutter omit.Val[bool] `db:"source_gutter" ` H3cell omitnull.Val[string] `db:"h3cell" ` AddressCountry omit.Val[string] `db:"address_country" ` @@ -276,7 +276,7 @@ func (s PublicreportNuisanceSetter) SetColumns() []string { if s.Status.IsValue() { vals = append(vals, "status") } - if !s.OrganizationID.IsUnset() { + if s.OrganizationID.IsValue() { vals = append(vals, "organization_id") } if s.SourceGutter.IsValue() { @@ -397,8 +397,8 @@ func (s PublicreportNuisanceSetter) Overwrite(t *PublicreportNuisance) { if s.Status.IsValue() { t.Status = s.Status.MustGet() } - if !s.OrganizationID.IsUnset() { - t.OrganizationID = s.OrganizationID.MustGetNull() + if s.OrganizationID.IsValue() { + t.OrganizationID = s.OrganizationID.MustGet() } if s.SourceGutter.IsValue() { t.SourceGutter = s.SourceGutter.MustGet() @@ -562,8 +562,8 @@ func (s *PublicreportNuisanceSetter) Apply(q *dialect.InsertQuery) { vals[12] = psql.Raw("DEFAULT") } - if !s.OrganizationID.IsUnset() { - vals[13] = psql.Arg(s.OrganizationID.MustGetNull()) + if s.OrganizationID.IsValue() { + vals[13] = psql.Arg(s.OrganizationID.MustGet()) } else { vals[13] = psql.Raw("DEFAULT") } @@ -820,7 +820,7 @@ func (s PublicreportNuisanceSetter) Expressions(prefix ...string) []bob.Expressi }}) } - if !s.OrganizationID.IsUnset() { + if s.OrganizationID.IsValue() { exprs = append(exprs, expr.Join{Sep: " = ", Exprs: []bob.Expression{ psql.Quote(append(prefix, "organization_id")...), psql.Arg(s.OrganizationID), @@ -1308,7 +1308,7 @@ func (o *PublicreportNuisance) Organization(mods ...bob.Mod[*dialect.SelectQuery } func (os PublicreportNuisanceSlice) Organization(mods ...bob.Mod[*dialect.SelectQuery]) OrganizationsQuery { - pkOrganizationID := make(pgtypes.Array[null.Val[int32]], 0, len(os)) + pkOrganizationID := make(pgtypes.Array[int32], 0, len(os)) for _, o := range os { if o == nil { continue @@ -1563,7 +1563,7 @@ func (publicreportNuisance0 *PublicreportNuisance) AttachAddress(ctx context.Con func attachPublicreportNuisanceOrganization0(ctx context.Context, exec bob.Executor, count int, publicreportNuisance0 *PublicreportNuisance, organization1 *Organization) (*PublicreportNuisance, error) { setter := &PublicreportNuisanceSetter{ - OrganizationID: omitnull.From(organization1.ID), + OrganizationID: omit.From(organization1.ID), } err := publicreportNuisance0.Update(ctx, exec, setter) @@ -1736,7 +1736,7 @@ type publicreportNuisanceWhere[Q psql.Filterable] struct { ReporterPhone psql.WhereNullMod[Q, string] AddressRaw psql.WhereMod[Q, string] Status psql.WhereMod[Q, enums.PublicreportReportstatustype] - OrganizationID psql.WhereNullMod[Q, int32] + OrganizationID psql.WhereMod[Q, int32] SourceGutter psql.WhereMod[Q, bool] H3cell psql.WhereNullMod[Q, string] AddressCountry psql.WhereMod[Q, string] @@ -1783,7 +1783,7 @@ func buildPublicreportNuisanceWhere[Q psql.Filterable](cols publicreportNuisance ReporterPhone: psql.WhereNull[Q, string](cols.ReporterPhone), AddressRaw: psql.Where[Q, string](cols.AddressRaw), Status: psql.Where[Q, enums.PublicreportReportstatustype](cols.Status), - OrganizationID: psql.WhereNull[Q, int32](cols.OrganizationID), + OrganizationID: psql.Where[Q, int32](cols.OrganizationID), SourceGutter: psql.Where[Q, bool](cols.SourceGutter), H3cell: psql.WhereNull[Q, string](cols.H3cell), AddressCountry: psql.Where[Q, string](cols.AddressCountry), @@ -2234,11 +2234,8 @@ func (os PublicreportNuisanceSlice) LoadOrganization(ctx context.Context, exec b } for _, rel := range organizations { - if !o.OrganizationID.IsValue() { - continue - } - if !(o.OrganizationID.IsValue() && o.OrganizationID.MustGet() == rel.ID) { + if !(o.OrganizationID == rel.ID) { continue } diff --git a/db/models/publicreport.water.bob.go b/db/models/publicreport.water.bob.go index 8465918d..cbe0933d 100644 --- a/db/models/publicreport.water.bob.go +++ b/db/models/publicreport.water.bob.go @@ -55,7 +55,7 @@ type PublicreportWater struct { ReporterName string `db:"reporter_name" ` ReporterPhone string `db:"reporter_phone" ` Status enums.PublicreportReportstatustype `db:"status" ` - OrganizationID null.Val[int32] `db:"organization_id" ` + OrganizationID int32 `db:"organization_id" ` HasBackyardPermission bool `db:"has_backyard_permission" ` IsReporterConfidential bool `db:"is_reporter_confidential" ` IsReporterOwner bool `db:"is_reporter_owner" ` @@ -219,7 +219,7 @@ type PublicreportWaterSetter struct { ReporterName omit.Val[string] `db:"reporter_name" ` ReporterPhone omit.Val[string] `db:"reporter_phone" ` Status omit.Val[enums.PublicreportReportstatustype] `db:"status" ` - OrganizationID omitnull.Val[int32] `db:"organization_id" ` + OrganizationID omit.Val[int32] `db:"organization_id" ` HasBackyardPermission omit.Val[bool] `db:"has_backyard_permission" ` IsReporterConfidential omit.Val[bool] `db:"is_reporter_confidential" ` IsReporterOwner omit.Val[bool] `db:"is_reporter_owner" ` @@ -317,7 +317,7 @@ func (s PublicreportWaterSetter) SetColumns() []string { if s.Status.IsValue() { vals = append(vals, "status") } - if !s.OrganizationID.IsUnset() { + if s.OrganizationID.IsValue() { vals = append(vals, "organization_id") } if s.HasBackyardPermission.IsValue() { @@ -435,8 +435,8 @@ func (s PublicreportWaterSetter) Overwrite(t *PublicreportWater) { if s.Status.IsValue() { t.Status = s.Status.MustGet() } - if !s.OrganizationID.IsUnset() { - t.OrganizationID = s.OrganizationID.MustGetNull() + if s.OrganizationID.IsValue() { + t.OrganizationID = s.OrganizationID.MustGet() } if s.HasBackyardPermission.IsValue() { t.HasBackyardPermission = s.HasBackyardPermission.MustGet() @@ -642,8 +642,8 @@ func (s *PublicreportWaterSetter) Apply(q *dialect.InsertQuery) { vals[27] = psql.Raw("DEFAULT") } - if !s.OrganizationID.IsUnset() { - vals[28] = psql.Arg(s.OrganizationID.MustGetNull()) + if s.OrganizationID.IsValue() { + vals[28] = psql.Arg(s.OrganizationID.MustGet()) } else { vals[28] = psql.Raw("DEFAULT") } @@ -909,7 +909,7 @@ func (s PublicreportWaterSetter) Expressions(prefix ...string) []bob.Expression }}) } - if !s.OrganizationID.IsUnset() { + if s.OrganizationID.IsValue() { exprs = append(exprs, expr.Join{Sep: " = ", Exprs: []bob.Expression{ psql.Quote(append(prefix, "organization_id")...), psql.Arg(s.OrganizationID), @@ -1285,7 +1285,7 @@ func (o *PublicreportWater) Organization(mods ...bob.Mod[*dialect.SelectQuery]) } func (os PublicreportWaterSlice) Organization(mods ...bob.Mod[*dialect.SelectQuery]) OrganizationsQuery { - pkOrganizationID := make(pgtypes.Array[null.Val[int32]], 0, len(os)) + pkOrganizationID := make(pgtypes.Array[int32], 0, len(os)) for _, o := range os { if o == nil { continue @@ -1540,7 +1540,7 @@ func (publicreportWater0 *PublicreportWater) AttachAddress(ctx context.Context, func attachPublicreportWaterOrganization0(ctx context.Context, exec bob.Executor, count int, publicreportWater0 *PublicreportWater, organization1 *Organization) (*PublicreportWater, error) { setter := &PublicreportWaterSetter{ - OrganizationID: omitnull.From(organization1.ID), + OrganizationID: omit.From(organization1.ID), } err := publicreportWater0.Update(ctx, exec, setter) @@ -1728,7 +1728,7 @@ type publicreportWaterWhere[Q psql.Filterable] struct { ReporterName psql.WhereMod[Q, string] ReporterPhone psql.WhereMod[Q, string] Status psql.WhereMod[Q, enums.PublicreportReportstatustype] - OrganizationID psql.WhereNullMod[Q, int32] + OrganizationID psql.WhereMod[Q, int32] HasBackyardPermission psql.WhereMod[Q, bool] IsReporterConfidential psql.WhereMod[Q, bool] IsReporterOwner psql.WhereMod[Q, bool] @@ -1774,7 +1774,7 @@ func buildPublicreportWaterWhere[Q psql.Filterable](cols publicreportWaterColumn ReporterName: psql.Where[Q, string](cols.ReporterName), ReporterPhone: psql.Where[Q, string](cols.ReporterPhone), Status: psql.Where[Q, enums.PublicreportReportstatustype](cols.Status), - OrganizationID: psql.WhereNull[Q, int32](cols.OrganizationID), + OrganizationID: psql.Where[Q, int32](cols.OrganizationID), HasBackyardPermission: psql.Where[Q, bool](cols.HasBackyardPermission), IsReporterConfidential: psql.Where[Q, bool](cols.IsReporterConfidential), IsReporterOwner: psql.Where[Q, bool](cols.IsReporterOwner), @@ -2209,11 +2209,8 @@ func (os PublicreportWaterSlice) LoadOrganization(ctx context.Context, exec bob. } for _, rel := range organizations { - if !o.OrganizationID.IsValue() { - continue - } - if !(o.OrganizationID.IsValue() && o.OrganizationID.MustGet() == rel.ID) { + if !(o.OrganizationID == rel.ID) { continue } diff --git a/platform/district.go b/platform/district.go index 6da7e2d1..d76945a8 100644 --- a/platform/district.go +++ b/platform/district.go @@ -13,6 +13,11 @@ import ( "github.com/rs/zerolog/log" ) +func DistrictCatchall(ctx context.Context) (*models.Organization, error) { + return models.Organizations.Query( + models.SelectWhere.Organizations.IsCatchall.EQ(true), + ).One(ctx, db.PGInstance.BobDB) +} func DistrictForLocation(ctx context.Context, lng float64, lat float64) (*models.Organization, error) { organizations, err := models.Organizations.Query( sm.Where( @@ -54,8 +59,12 @@ func MatchDistrict(ctx context.Context, longitude, latitude *float64, images []I } } if longitude == nil || latitude == nil { - log.Debug().Msg("No location from images, no latlng for the report itself, cannot match") - return nil, nil + org, err = DistrictCatchall(ctx) + if err != nil { + return nil, fmt.Errorf("get catchall: %w", err) + } + log.Debug().Int32("id", org.ID).Msg("No location from images, no latlng for the report itself, using catchall") + return &org.ID, nil } org, err = DistrictForLocation(ctx, *longitude, *latitude) if err != nil { @@ -63,8 +72,12 @@ func MatchDistrict(ctx context.Context, longitude, latitude *float64, images []I return nil, fmt.Errorf("Failed to get district for location: %w", err) } if org == nil { - log.Debug().Err(err).Float64("lng", *longitude).Float64("lat", *latitude).Msg("No district match by report location") - return nil, nil + org, err = DistrictCatchall(ctx) + if err != nil { + return nil, fmt.Errorf("get catchall: %w", err) + } + log.Debug().Err(err).Float64("lng", *longitude).Float64("lat", *latitude).Int32("id", org.ID).Msg("No district match by report location, using catchall") + return &org.ID, nil } log.Debug().Err(err).Int32("org_id", org.ID).Float64("lng", *longitude).Float64("lat", *latitude).Msg("Found district match by report location") return &org.ID, nil diff --git a/platform/nuisance.go b/platform/nuisance.go index 4ee572e0..cf63e09f 100644 --- a/platform/nuisance.go +++ b/platform/nuisance.go @@ -57,7 +57,7 @@ func NuisanceCreate(ctx context.Context, setter models.PublicreportNuisanceSette setter.AddressID = omitnull.From(a.ID) } if organization_id != nil { - setter.OrganizationID = omitnull.FromPtr(organization_id) + setter.OrganizationID = omit.FromPtr(organization_id) } nuisance, err := models.PublicreportNuisances.Insert(&setter).One(ctx, txn) if err != nil { diff --git a/platform/water.go b/platform/water.go index d37d07ec..f55221b0 100644 --- a/platform/water.go +++ b/platform/water.go @@ -56,7 +56,7 @@ func WaterCreate(ctx context.Context, setter models.PublicreportWaterSetter, lat setter.AddressID = omitnull.From(a.ID) } if organization_id != nil { - setter.OrganizationID = omitnull.FromPtr(organization_id) + setter.OrganizationID = omit.FromPtr(organization_id) } water, err := models.PublicreportWaters.Insert(&setter).One(ctx, txn) diff --git a/rmo/status.go b/rmo/status.go index 25610f15..2eed8835 100644 --- a/rmo/status.go +++ b/rmo/status.go @@ -108,14 +108,12 @@ func contentFromNuisance(ctx context.Context, report_id string) (result ContentS return result, fmt.Errorf("Failed to get images %s: %w", report_id, err) } - if !nuisance.OrganizationID.IsNull() { - org_id := nuisance.OrganizationID.MustGet() - org, err := models.FindOrganization(ctx, db.PGInstance.BobDB, org_id) - if err != nil { - return result, fmt.Errorf("Failed to get district %d information: %w", org_id, err) - } - result.District = newContentDistrict(org) + org_id := nuisance.OrganizationID + org, err := models.FindOrganization(ctx, db.PGInstance.BobDB, org_id) + if err != nil { + return result, fmt.Errorf("Failed to get district %d information: %w", org_id, err) } + result.District = newContentDistrict(org) result.Report.ID = report_id result.Report.Address = nuisance.AddressRaw result.Report.Created = nuisance.Created @@ -214,15 +212,12 @@ func contentFromWater(ctx context.Context, report_id string) (result ContentStat return result, fmt.Errorf("Failed to get images %s: %w", report_id, err) } - if !water.OrganizationID.IsNull() { - org_id := water.OrganizationID.MustGet() - org, err := models.FindOrganization(ctx, db.PGInstance.BobDB, org_id) - if err != nil { - return result, fmt.Errorf("Failed to get district %d information: %w", org_id, err) - } - result.District = newContentDistrict(org) + org_id := water.OrganizationID + org, err := models.FindOrganization(ctx, db.PGInstance.BobDB, org_id) + if err != nil { + return result, fmt.Errorf("Failed to get district %d information: %w", org_id, err) } - + result.District = newContentDistrict(org) result.Report.ID = report_id result.Report.Address = water.AddressRaw result.Report.Created = water.Created