From 3c8436fe10379102a04d5e0a4222d765e93cd820 Mon Sep 17 00:00:00 2001 From: Eli Ribble Date: Thu, 8 Jan 2026 15:00:30 +0000 Subject: [PATCH] Begin the process of saving quick reports --- config/config.go | 12 +- db/bobgen.yaml | 1 + db/dberrors/publicreport.quick.bob.go | 17 + db/dberrors/publicreport.quick_photo.bob.go | 17 + db/dbinfo/publicreport.quick.bob.go | 142 ++++ db/dbinfo/publicreport.quick_photo.bob.go | 147 ++++ db/factory/bobfactory_context.bob.go | 8 + db/factory/bobfactory_main.bob.go | 85 +++ db/factory/bobfactory_main.bob_test.go | 48 ++ db/factory/publicreport.quick.bob.go | 602 +++++++++++++++ db/factory/publicreport.quick_photo.bob.go | 498 ++++++++++++ db/migrations/00024_public_report.sql | 24 + db/models/bob_joins.bob.go | 4 + db/models/bob_loaders.bob.go | 8 + db/models/bob_types.bob_test.go | 6 + db/models/bob_where.bob.go | 6 + db/models/publicreport.quick.bob.go | 721 ++++++++++++++++++ db/models/publicreport.quick_photo.bob.go | 678 ++++++++++++++++ db/sql/trapcount_by_location_id.bob_test.go | 1 - ...trapdata_by_location_id_recent.bob_test.go | 1 - h3utils/h3.go | 2 +- htmlpage/html.go | 4 +- htmlpage/public-reports/template/quick.html | 6 +- public-report/endpoint.go | 75 +- queue/label_studio.go | 2 +- userfile/userfile.go | 31 +- 26 files changed, 3125 insertions(+), 21 deletions(-) create mode 100644 db/dberrors/publicreport.quick.bob.go create mode 100644 db/dberrors/publicreport.quick_photo.bob.go create mode 100644 db/dbinfo/publicreport.quick.bob.go create mode 100644 db/dbinfo/publicreport.quick_photo.bob.go create mode 100644 db/factory/publicreport.quick.bob.go create mode 100644 db/factory/publicreport.quick_photo.bob.go create mode 100644 db/migrations/00024_public_report.sql create mode 100644 db/models/publicreport.quick.bob.go create mode 100644 db/models/publicreport.quick_photo.bob.go diff --git a/config/config.go b/config/config.go index 81df0fc4..94184e6a 100644 --- a/config/config.go +++ b/config/config.go @@ -7,7 +7,7 @@ import ( "strconv" ) -var Bind, ClientID, ClientSecret, Environment, FieldseekerSchemaDirectory, MapboxToken, PGDSN, URLReport, URLSync, UserFilesDirectory string +var Bind, ClientID, ClientSecret, Environment, FieldseekerSchemaDirectory, MapboxToken, PGDSN, URLReport, URLSync, FilesDirectoryPublic, FilesDirectoryUser string // Build the ArcGIS authorization URL with PKCE func BuildArcGISAuthURL(clientID string) string { @@ -82,9 +82,13 @@ func Parse() error { if FieldseekerSchemaDirectory == "" { return fmt.Errorf("You must specify a non-empty FIELDSEEKER_SCHEMA_DIRECTORY") } - UserFilesDirectory = os.Getenv("USER_FILES_DIRECTORY") - if UserFilesDirectory == "" { - return fmt.Errorf("You must specify a non-empty USER_FILES_DIRECTORY") + FilesDirectoryPublic = os.Getenv("FILES_DIRECTORY_PUBLIC") + if FilesDirectoryPublic == "" { + return fmt.Errorf("You must specify a non-empty FILES_DIRECTORY_PUBLIC") + } + FilesDirectoryUser = os.Getenv("FILES_DIRECTORY_USER") + if FilesDirectoryUser == "" { + return fmt.Errorf("You must specify a non-empty FILES_DIRECTORY_USER") } return nil } diff --git a/db/bobgen.yaml b/db/bobgen.yaml index 41eacc7e..7678b9a1 100644 --- a/db/bobgen.yaml +++ b/db/bobgen.yaml @@ -7,6 +7,7 @@ aliases: psql: schemas: - "public" + - "publicreport" - "fieldseeker" queries: - ./sql diff --git a/db/dberrors/publicreport.quick.bob.go b/db/dberrors/publicreport.quick.bob.go new file mode 100644 index 00000000..cbd533e1 --- /dev/null +++ b/db/dberrors/publicreport.quick.bob.go @@ -0,0 +1,17 @@ +// Code generated by BobGen psql v0.0.4-0.20260105020634-53e08d840e47+dirty. DO NOT EDIT. +// This file is meant to be re-generated in place and/or deleted at any time. + +package dberrors + +var PublicreportQuickErrors = &publicreportQuickErrors{ + ErrUniqueQuickPkey: &UniqueConstraintError{ + schema: "publicreport", + table: "quick", + columns: []string{"id"}, + s: "quick_pkey", + }, +} + +type publicreportQuickErrors struct { + ErrUniqueQuickPkey *UniqueConstraintError +} diff --git a/db/dberrors/publicreport.quick_photo.bob.go b/db/dberrors/publicreport.quick_photo.bob.go new file mode 100644 index 00000000..cce0eee3 --- /dev/null +++ b/db/dberrors/publicreport.quick_photo.bob.go @@ -0,0 +1,17 @@ +// Code generated by BobGen psql v0.0.4-0.20260105020634-53e08d840e47+dirty. DO NOT EDIT. +// This file is meant to be re-generated in place and/or deleted at any time. + +package dberrors + +var PublicreportQuickPhotoErrors = &publicreportQuickPhotoErrors{ + ErrUniqueQuickPhotoPkey: &UniqueConstraintError{ + schema: "publicreport", + table: "quick_photo", + columns: []string{"id"}, + s: "quick_photo_pkey", + }, +} + +type publicreportQuickPhotoErrors struct { + ErrUniqueQuickPhotoPkey *UniqueConstraintError +} diff --git a/db/dbinfo/publicreport.quick.bob.go b/db/dbinfo/publicreport.quick.bob.go new file mode 100644 index 00000000..20de6e04 --- /dev/null +++ b/db/dbinfo/publicreport.quick.bob.go @@ -0,0 +1,142 @@ +// Code generated by BobGen psql v0.0.4-0.20260105020634-53e08d840e47+dirty. DO NOT EDIT. +// This file is meant to be re-generated in place and/or deleted at any time. + +package dbinfo + +import "github.com/aarondl/opt/null" + +var PublicreportQuicks = Table[ + publicreportQuickColumns, + publicreportQuickIndexes, + publicreportQuickForeignKeys, + publicreportQuickUniques, + publicreportQuickChecks, +]{ + Schema: "publicreport", + Name: "quick", + Columns: publicreportQuickColumns{ + ID: column{ + Name: "id", + DBType: "integer", + Default: "nextval('publicreport.quick_id_seq'::regclass)", + Comment: "", + Nullable: false, + Generated: false, + AutoIncr: false, + }, + Created: column{ + Name: "created", + DBType: "timestamp without time zone", + Default: "", + Comment: "", + Nullable: false, + Generated: false, + AutoIncr: false, + }, + Comments: column{ + Name: "comments", + DBType: "text", + Default: "", + Comment: "", + Nullable: false, + Generated: false, + AutoIncr: false, + }, + Location: column{ + Name: "location", + DBType: "geography", + Default: "NULL", + Comment: "", + Nullable: true, + Generated: false, + AutoIncr: false, + }, + H3cell: column{ + Name: "h3cell", + DBType: "h3index", + Default: "NULL", + Comment: "", + Nullable: true, + Generated: false, + AutoIncr: false, + }, + UUID: column{ + Name: "uuid", + DBType: "uuid", + Default: "", + Comment: "", + Nullable: false, + Generated: false, + AutoIncr: false, + }, + }, + Indexes: publicreportQuickIndexes{ + QuickPkey: index{ + Type: "btree", + Name: "quick_pkey", + Columns: []indexColumn{ + { + Name: "id", + Desc: null.FromCond(false, true), + IsExpression: false, + }, + }, + Unique: true, + Comment: "", + NullsFirst: []bool{false}, + NullsDistinct: false, + Where: "", + Include: []string{}, + }, + }, + PrimaryKey: &constraint{ + Name: "quick_pkey", + Columns: []string{"id"}, + Comment: "", + }, + + Comment: "", +} + +type publicreportQuickColumns struct { + ID column + Created column + Comments column + Location column + H3cell column + UUID column +} + +func (c publicreportQuickColumns) AsSlice() []column { + return []column{ + c.ID, c.Created, c.Comments, c.Location, c.H3cell, c.UUID, + } +} + +type publicreportQuickIndexes struct { + QuickPkey index +} + +func (i publicreportQuickIndexes) AsSlice() []index { + return []index{ + i.QuickPkey, + } +} + +type publicreportQuickForeignKeys struct{} + +func (f publicreportQuickForeignKeys) AsSlice() []foreignKey { + return []foreignKey{} +} + +type publicreportQuickUniques struct{} + +func (u publicreportQuickUniques) AsSlice() []constraint { + return []constraint{} +} + +type publicreportQuickChecks struct{} + +func (c publicreportQuickChecks) AsSlice() []check { + return []check{} +} diff --git a/db/dbinfo/publicreport.quick_photo.bob.go b/db/dbinfo/publicreport.quick_photo.bob.go new file mode 100644 index 00000000..9a7d4eca --- /dev/null +++ b/db/dbinfo/publicreport.quick_photo.bob.go @@ -0,0 +1,147 @@ +// Code generated by BobGen psql v0.0.4-0.20260105020634-53e08d840e47+dirty. DO NOT EDIT. +// This file is meant to be re-generated in place and/or deleted at any time. + +package dbinfo + +import "github.com/aarondl/opt/null" + +var PublicreportQuickPhotos = Table[ + publicreportQuickPhotoColumns, + publicreportQuickPhotoIndexes, + publicreportQuickPhotoForeignKeys, + publicreportQuickPhotoUniques, + publicreportQuickPhotoChecks, +]{ + Schema: "publicreport", + Name: "quick_photo", + Columns: publicreportQuickPhotoColumns{ + ID: column{ + Name: "id", + DBType: "integer", + Default: "nextval('publicreport.quick_photo_id_seq'::regclass)", + Comment: "", + Nullable: false, + Generated: false, + AutoIncr: false, + }, + Size: column{ + Name: "size", + DBType: "bigint", + Default: "", + Comment: "", + Nullable: false, + Generated: false, + AutoIncr: false, + }, + Filename: column{ + Name: "filename", + DBType: "text", + Default: "", + Comment: "", + Nullable: false, + Generated: false, + AutoIncr: false, + }, + QuickID: column{ + Name: "quick_id", + DBType: "integer", + Default: "", + Comment: "", + Nullable: false, + Generated: false, + AutoIncr: false, + }, + UUID: column{ + Name: "uuid", + DBType: "uuid", + Default: "", + Comment: "", + Nullable: false, + Generated: false, + AutoIncr: false, + }, + }, + Indexes: publicreportQuickPhotoIndexes{ + QuickPhotoPkey: index{ + Type: "btree", + Name: "quick_photo_pkey", + Columns: []indexColumn{ + { + Name: "id", + Desc: null.FromCond(false, true), + IsExpression: false, + }, + }, + Unique: true, + Comment: "", + NullsFirst: []bool{false}, + NullsDistinct: false, + Where: "", + Include: []string{}, + }, + }, + PrimaryKey: &constraint{ + Name: "quick_photo_pkey", + Columns: []string{"id"}, + Comment: "", + }, + ForeignKeys: publicreportQuickPhotoForeignKeys{ + PublicreportQuickPhotoQuickPhotoQuickIDFkey: foreignKey{ + constraint: constraint{ + Name: "publicreport.quick_photo.quick_photo_quick_id_fkey", + Columns: []string{"quick_id"}, + Comment: "", + }, + ForeignTable: "publicreport.quick", + ForeignColumns: []string{"id"}, + }, + }, + + Comment: "", +} + +type publicreportQuickPhotoColumns struct { + ID column + Size column + Filename column + QuickID column + UUID column +} + +func (c publicreportQuickPhotoColumns) AsSlice() []column { + return []column{ + c.ID, c.Size, c.Filename, c.QuickID, c.UUID, + } +} + +type publicreportQuickPhotoIndexes struct { + QuickPhotoPkey index +} + +func (i publicreportQuickPhotoIndexes) AsSlice() []index { + return []index{ + i.QuickPhotoPkey, + } +} + +type publicreportQuickPhotoForeignKeys struct { + PublicreportQuickPhotoQuickPhotoQuickIDFkey foreignKey +} + +func (f publicreportQuickPhotoForeignKeys) AsSlice() []foreignKey { + return []foreignKey{ + f.PublicreportQuickPhotoQuickPhotoQuickIDFkey, + } +} + +type publicreportQuickPhotoUniques struct{} + +func (u publicreportQuickPhotoUniques) AsSlice() []constraint { + return []constraint{} +} + +type publicreportQuickPhotoChecks struct{} + +func (c publicreportQuickPhotoChecks) AsSlice() []check { + return []check{} +} diff --git a/db/factory/bobfactory_context.bob.go b/db/factory/bobfactory_context.bob.go index d6041b63..3cb78550 100644 --- a/db/factory/bobfactory_context.bob.go +++ b/db/factory/bobfactory_context.bob.go @@ -208,6 +208,14 @@ var ( organizationRelNoteImagesCtx = newContextual[bool]("note_image.organization.note_image.note_image_organization_id_fkey") organizationRelUserCtx = newContextual[bool]("organization.user_.user_.user__organization_id_fkey") + // Relationship Contexts for publicreport.quick + publicreportQuickWithParentsCascadingCtx = newContextual[bool]("publicreportQuickWithParentsCascading") + publicreportQuickRelQuickPhotosCtx = newContextual[bool]("publicreport.quick.publicreport.quick_photo.publicreport.quick_photo.quick_photo_quick_id_fkey") + + // Relationship Contexts for publicreport.quick_photo + publicreportQuickPhotoWithParentsCascadingCtx = newContextual[bool]("publicreportQuickPhotoWithParentsCascading") + publicreportQuickPhotoRelQuickCtx = newContextual[bool]("publicreport.quick.publicreport.quick_photo.publicreport.quick_photo.quick_photo_quick_id_fkey") + // Relationship Contexts for raster_columns rasterColumnWithParentsCascadingCtx = newContextual[bool]("rasterColumnWithParentsCascading") diff --git a/db/factory/bobfactory_main.bob.go b/db/factory/bobfactory_main.bob.go index fb604907..0321918b 100644 --- a/db/factory/bobfactory_main.bob.go +++ b/db/factory/bobfactory_main.bob.go @@ -58,6 +58,8 @@ type Factory struct { baseNotificationMods NotificationModSlice baseOauthTokenMods OauthTokenModSlice baseOrganizationMods OrganizationModSlice + basePublicreportQuickMods PublicreportQuickModSlice + basePublicreportQuickPhotoMods PublicreportQuickPhotoModSlice baseRasterColumnMods RasterColumnModSlice baseRasterOverviewMods RasterOverviewModSlice baseSessionMods SessionModSlice @@ -2370,6 +2372,73 @@ func (f *Factory) FromExistingOrganization(m *models.Organization) *Organization return o } +func (f *Factory) NewPublicreportQuick(mods ...PublicreportQuickMod) *PublicreportQuickTemplate { + return f.NewPublicreportQuickWithContext(context.Background(), mods...) +} + +func (f *Factory) NewPublicreportQuickWithContext(ctx context.Context, mods ...PublicreportQuickMod) *PublicreportQuickTemplate { + o := &PublicreportQuickTemplate{f: f} + + if f != nil { + f.basePublicreportQuickMods.Apply(ctx, o) + } + + PublicreportQuickModSlice(mods).Apply(ctx, o) + + return o +} + +func (f *Factory) FromExistingPublicreportQuick(m *models.PublicreportQuick) *PublicreportQuickTemplate { + o := &PublicreportQuickTemplate{f: f, alreadyPersisted: true} + + o.ID = func() int32 { return m.ID } + o.Created = func() time.Time { return m.Created } + o.Comments = func() string { return m.Comments } + o.Location = func() null.Val[string] { return m.Location } + o.H3cell = func() null.Val[string] { return m.H3cell } + o.UUID = func() uuid.UUID { return m.UUID } + + ctx := context.Background() + if len(m.R.QuickPhotos) > 0 { + PublicreportQuickMods.AddExistingQuickPhotos(m.R.QuickPhotos...).Apply(ctx, o) + } + + return o +} + +func (f *Factory) NewPublicreportQuickPhoto(mods ...PublicreportQuickPhotoMod) *PublicreportQuickPhotoTemplate { + return f.NewPublicreportQuickPhotoWithContext(context.Background(), mods...) +} + +func (f *Factory) NewPublicreportQuickPhotoWithContext(ctx context.Context, mods ...PublicreportQuickPhotoMod) *PublicreportQuickPhotoTemplate { + o := &PublicreportQuickPhotoTemplate{f: f} + + if f != nil { + f.basePublicreportQuickPhotoMods.Apply(ctx, o) + } + + PublicreportQuickPhotoModSlice(mods).Apply(ctx, o) + + return o +} + +func (f *Factory) FromExistingPublicreportQuickPhoto(m *models.PublicreportQuickPhoto) *PublicreportQuickPhotoTemplate { + o := &PublicreportQuickPhotoTemplate{f: f, alreadyPersisted: true} + + o.ID = func() int32 { return m.ID } + o.Size = func() int64 { return m.Size } + o.Filename = func() string { return m.Filename } + o.QuickID = func() int32 { return m.QuickID } + o.UUID = func() uuid.UUID { return m.UUID } + + ctx := context.Background() + if m.R.Quick != nil { + PublicreportQuickPhotoMods.WithExistingQuick(m.R.Quick).Apply(ctx, o) + } + + return o +} + func (f *Factory) NewRasterColumn(mods ...RasterColumnMod) *RasterColumnTemplate { return f.NewRasterColumnWithContext(context.Background(), mods...) } @@ -2882,6 +2951,22 @@ func (f *Factory) AddBaseOrganizationMod(mods ...OrganizationMod) { f.baseOrganizationMods = append(f.baseOrganizationMods, mods...) } +func (f *Factory) ClearBasePublicreportQuickMods() { + f.basePublicreportQuickMods = nil +} + +func (f *Factory) AddBasePublicreportQuickMod(mods ...PublicreportQuickMod) { + f.basePublicreportQuickMods = append(f.basePublicreportQuickMods, mods...) +} + +func (f *Factory) ClearBasePublicreportQuickPhotoMods() { + f.basePublicreportQuickPhotoMods = nil +} + +func (f *Factory) AddBasePublicreportQuickPhotoMod(mods ...PublicreportQuickPhotoMod) { + f.basePublicreportQuickPhotoMods = append(f.basePublicreportQuickPhotoMods, mods...) +} + func (f *Factory) ClearBaseRasterColumnMods() { f.baseRasterColumnMods = nil } diff --git a/db/factory/bobfactory_main.bob_test.go b/db/factory/bobfactory_main.bob_test.go index 92c2ac82..5cd4ebd9 100644 --- a/db/factory/bobfactory_main.bob_test.go +++ b/db/factory/bobfactory_main.bob_test.go @@ -944,6 +944,54 @@ func TestCreateOrganization(t *testing.T) { } } +func TestCreatePublicreportQuick(t *testing.T) { + if testDB == nil { + t.Skip("skipping test, no DSN provided") + } + + ctx, cancel := context.WithCancel(t.Context()) + t.Cleanup(cancel) + + tx, err := testDB.Begin(ctx) + if err != nil { + t.Fatalf("Error starting transaction: %v", err) + } + + defer func() { + if err := tx.Rollback(ctx); err != nil { + t.Fatalf("Error rolling back transaction: %v", err) + } + }() + + if _, err := New().NewPublicreportQuickWithContext(ctx).Create(ctx, tx); err != nil { + t.Fatalf("Error creating PublicreportQuick: %v", err) + } +} + +func TestCreatePublicreportQuickPhoto(t *testing.T) { + if testDB == nil { + t.Skip("skipping test, no DSN provided") + } + + ctx, cancel := context.WithCancel(t.Context()) + t.Cleanup(cancel) + + tx, err := testDB.Begin(ctx) + if err != nil { + t.Fatalf("Error starting transaction: %v", err) + } + + defer func() { + if err := tx.Rollback(ctx); err != nil { + t.Fatalf("Error rolling back transaction: %v", err) + } + }() + + if _, err := New().NewPublicreportQuickPhotoWithContext(ctx).Create(ctx, tx); err != nil { + t.Fatalf("Error creating PublicreportQuickPhoto: %v", err) + } +} + func TestCreateSession(t *testing.T) { if testDB == nil { t.Skip("skipping test, no DSN provided") diff --git a/db/factory/publicreport.quick.bob.go b/db/factory/publicreport.quick.bob.go new file mode 100644 index 00000000..e69c2bc6 --- /dev/null +++ b/db/factory/publicreport.quick.bob.go @@ -0,0 +1,602 @@ +// Code generated by BobGen psql v0.0.4-0.20260105020634-53e08d840e47+dirty. DO NOT EDIT. +// This file is meant to be re-generated in place and/or deleted at any time. + +package factory + +import ( + "context" + "testing" + "time" + + models "github.com/Gleipnir-Technology/nidus-sync/db/models" + "github.com/aarondl/opt/null" + "github.com/aarondl/opt/omit" + "github.com/aarondl/opt/omitnull" + "github.com/google/uuid" + "github.com/jaswdr/faker/v2" + "github.com/stephenafamo/bob" +) + +type PublicreportQuickMod interface { + Apply(context.Context, *PublicreportQuickTemplate) +} + +type PublicreportQuickModFunc func(context.Context, *PublicreportQuickTemplate) + +func (f PublicreportQuickModFunc) Apply(ctx context.Context, n *PublicreportQuickTemplate) { + f(ctx, n) +} + +type PublicreportQuickModSlice []PublicreportQuickMod + +func (mods PublicreportQuickModSlice) Apply(ctx context.Context, n *PublicreportQuickTemplate) { + for _, f := range mods { + f.Apply(ctx, n) + } +} + +// PublicreportQuickTemplate is an object representing the database table. +// all columns are optional and should be set by mods +type PublicreportQuickTemplate struct { + ID func() int32 + Created func() time.Time + Comments func() string + Location func() null.Val[string] + H3cell func() null.Val[string] + UUID func() uuid.UUID + + r publicreportQuickR + f *Factory + + alreadyPersisted bool +} + +type publicreportQuickR struct { + QuickPhotos []*publicreportQuickRQuickPhotosR +} + +type publicreportQuickRQuickPhotosR struct { + number int + o *PublicreportQuickPhotoTemplate +} + +// Apply mods to the PublicreportQuickTemplate +func (o *PublicreportQuickTemplate) Apply(ctx context.Context, mods ...PublicreportQuickMod) { + for _, mod := range mods { + mod.Apply(ctx, o) + } +} + +// setModelRels creates and sets the relationships on *models.PublicreportQuick +// according to the relationships in the template. Nothing is inserted into the db +func (t PublicreportQuickTemplate) setModelRels(o *models.PublicreportQuick) { + if t.r.QuickPhotos != nil { + rel := models.PublicreportQuickPhotoSlice{} + for _, r := range t.r.QuickPhotos { + related := r.o.BuildMany(r.number) + for _, rel := range related { + rel.QuickID = o.ID // h2 + rel.R.Quick = o + } + rel = append(rel, related...) + } + o.R.QuickPhotos = rel + } +} + +// BuildSetter returns an *models.PublicreportQuickSetter +// this does nothing with the relationship templates +func (o PublicreportQuickTemplate) BuildSetter() *models.PublicreportQuickSetter { + m := &models.PublicreportQuickSetter{} + + if o.ID != nil { + val := o.ID() + m.ID = omit.From(val) + } + if o.Created != nil { + val := o.Created() + m.Created = omit.From(val) + } + if o.Comments != nil { + val := o.Comments() + m.Comments = omit.From(val) + } + if o.Location != nil { + val := o.Location() + m.Location = omitnull.FromNull(val) + } + if o.H3cell != nil { + val := o.H3cell() + m.H3cell = omitnull.FromNull(val) + } + if o.UUID != nil { + val := o.UUID() + m.UUID = omit.From(val) + } + + return m +} + +// BuildManySetter returns an []*models.PublicreportQuickSetter +// this does nothing with the relationship templates +func (o PublicreportQuickTemplate) BuildManySetter(number int) []*models.PublicreportQuickSetter { + m := make([]*models.PublicreportQuickSetter, number) + + for i := range m { + m[i] = o.BuildSetter() + } + + return m +} + +// Build returns an *models.PublicreportQuick +// Related objects are also created and placed in the .R field +// NOTE: Objects are not inserted into the database. Use PublicreportQuickTemplate.Create +func (o PublicreportQuickTemplate) Build() *models.PublicreportQuick { + m := &models.PublicreportQuick{} + + if o.ID != nil { + m.ID = o.ID() + } + if o.Created != nil { + m.Created = o.Created() + } + if o.Comments != nil { + m.Comments = o.Comments() + } + if o.Location != nil { + m.Location = o.Location() + } + if o.H3cell != nil { + m.H3cell = o.H3cell() + } + if o.UUID != nil { + m.UUID = o.UUID() + } + + o.setModelRels(m) + + return m +} + +// BuildMany returns an models.PublicreportQuickSlice +// Related objects are also created and placed in the .R field +// NOTE: Objects are not inserted into the database. Use PublicreportQuickTemplate.CreateMany +func (o PublicreportQuickTemplate) BuildMany(number int) models.PublicreportQuickSlice { + m := make(models.PublicreportQuickSlice, number) + + for i := range m { + m[i] = o.Build() + } + + return m +} + +func ensureCreatablePublicreportQuick(m *models.PublicreportQuickSetter) { + if !(m.Created.IsValue()) { + val := random_time_Time(nil) + m.Created = omit.From(val) + } + if !(m.Comments.IsValue()) { + val := random_string(nil) + m.Comments = omit.From(val) + } + if !(m.UUID.IsValue()) { + val := random_uuid_UUID(nil) + m.UUID = omit.From(val) + } +} + +// insertOptRels creates and inserts any optional the relationships on *models.PublicreportQuick +// according to the relationships in the template. +// any required relationship should have already exist on the model +func (o *PublicreportQuickTemplate) insertOptRels(ctx context.Context, exec bob.Executor, m *models.PublicreportQuick) error { + var err error + + isQuickPhotosDone, _ := publicreportQuickRelQuickPhotosCtx.Value(ctx) + if !isQuickPhotosDone && o.r.QuickPhotos != nil { + ctx = publicreportQuickRelQuickPhotosCtx.WithValue(ctx, true) + for _, r := range o.r.QuickPhotos { + if r.o.alreadyPersisted { + m.R.QuickPhotos = append(m.R.QuickPhotos, r.o.Build()) + } else { + rel0, err := r.o.CreateMany(ctx, exec, r.number) + if err != nil { + return err + } + + err = m.AttachQuickPhotos(ctx, exec, rel0...) + if err != nil { + return err + } + } + } + } + + return err +} + +// Create builds a publicreportQuick and inserts it into the database +// Relations objects are also inserted and placed in the .R field +func (o *PublicreportQuickTemplate) Create(ctx context.Context, exec bob.Executor) (*models.PublicreportQuick, error) { + var err error + opt := o.BuildSetter() + ensureCreatablePublicreportQuick(opt) + + m, err := models.PublicreportQuicks.Insert(opt).One(ctx, exec) + if err != nil { + return nil, err + } + + if err := o.insertOptRels(ctx, exec, m); err != nil { + return nil, err + } + return m, err +} + +// MustCreate builds a publicreportQuick and inserts it into the database +// Relations objects are also inserted and placed in the .R field +// panics if an error occurs +func (o *PublicreportQuickTemplate) MustCreate(ctx context.Context, exec bob.Executor) *models.PublicreportQuick { + m, err := o.Create(ctx, exec) + if err != nil { + panic(err) + } + return m +} + +// CreateOrFail builds a publicreportQuick and inserts it into the database +// Relations objects are also inserted and placed in the .R field +// It calls `tb.Fatal(err)` on the test/benchmark if an error occurs +func (o *PublicreportQuickTemplate) CreateOrFail(ctx context.Context, tb testing.TB, exec bob.Executor) *models.PublicreportQuick { + tb.Helper() + m, err := o.Create(ctx, exec) + if err != nil { + tb.Fatal(err) + return nil + } + return m +} + +// CreateMany builds multiple publicreportQuicks and inserts them into the database +// Relations objects are also inserted and placed in the .R field +func (o PublicreportQuickTemplate) CreateMany(ctx context.Context, exec bob.Executor, number int) (models.PublicreportQuickSlice, error) { + var err error + m := make(models.PublicreportQuickSlice, number) + + for i := range m { + m[i], err = o.Create(ctx, exec) + if err != nil { + return nil, err + } + } + + return m, nil +} + +// MustCreateMany builds multiple publicreportQuicks and inserts them into the database +// Relations objects are also inserted and placed in the .R field +// panics if an error occurs +func (o PublicreportQuickTemplate) MustCreateMany(ctx context.Context, exec bob.Executor, number int) models.PublicreportQuickSlice { + m, err := o.CreateMany(ctx, exec, number) + if err != nil { + panic(err) + } + return m +} + +// CreateManyOrFail builds multiple publicreportQuicks and inserts them into the database +// Relations objects are also inserted and placed in the .R field +// It calls `tb.Fatal(err)` on the test/benchmark if an error occurs +func (o PublicreportQuickTemplate) CreateManyOrFail(ctx context.Context, tb testing.TB, exec bob.Executor, number int) models.PublicreportQuickSlice { + tb.Helper() + m, err := o.CreateMany(ctx, exec, number) + if err != nil { + tb.Fatal(err) + return nil + } + return m +} + +// PublicreportQuick has methods that act as mods for the PublicreportQuickTemplate +var PublicreportQuickMods publicreportQuickMods + +type publicreportQuickMods struct{} + +func (m publicreportQuickMods) RandomizeAllColumns(f *faker.Faker) PublicreportQuickMod { + return PublicreportQuickModSlice{ + PublicreportQuickMods.RandomID(f), + PublicreportQuickMods.RandomCreated(f), + PublicreportQuickMods.RandomComments(f), + PublicreportQuickMods.RandomLocation(f), + PublicreportQuickMods.RandomH3cell(f), + PublicreportQuickMods.RandomUUID(f), + } +} + +// Set the model columns to this value +func (m publicreportQuickMods) ID(val int32) PublicreportQuickMod { + return PublicreportQuickModFunc(func(_ context.Context, o *PublicreportQuickTemplate) { + o.ID = func() int32 { return val } + }) +} + +// Set the Column from the function +func (m publicreportQuickMods) IDFunc(f func() int32) PublicreportQuickMod { + return PublicreportQuickModFunc(func(_ context.Context, o *PublicreportQuickTemplate) { + o.ID = f + }) +} + +// Clear any values for the column +func (m publicreportQuickMods) UnsetID() PublicreportQuickMod { + return PublicreportQuickModFunc(func(_ context.Context, o *PublicreportQuickTemplate) { + o.ID = nil + }) +} + +// Generates a random value for the column using the given faker +// if faker is nil, a default faker is used +func (m publicreportQuickMods) RandomID(f *faker.Faker) PublicreportQuickMod { + return PublicreportQuickModFunc(func(_ context.Context, o *PublicreportQuickTemplate) { + o.ID = func() int32 { + return random_int32(f) + } + }) +} + +// Set the model columns to this value +func (m publicreportQuickMods) Created(val time.Time) PublicreportQuickMod { + return PublicreportQuickModFunc(func(_ context.Context, o *PublicreportQuickTemplate) { + o.Created = func() time.Time { return val } + }) +} + +// Set the Column from the function +func (m publicreportQuickMods) CreatedFunc(f func() time.Time) PublicreportQuickMod { + return PublicreportQuickModFunc(func(_ context.Context, o *PublicreportQuickTemplate) { + o.Created = f + }) +} + +// Clear any values for the column +func (m publicreportQuickMods) UnsetCreated() PublicreportQuickMod { + return PublicreportQuickModFunc(func(_ context.Context, o *PublicreportQuickTemplate) { + o.Created = nil + }) +} + +// Generates a random value for the column using the given faker +// if faker is nil, a default faker is used +func (m publicreportQuickMods) RandomCreated(f *faker.Faker) PublicreportQuickMod { + return PublicreportQuickModFunc(func(_ context.Context, o *PublicreportQuickTemplate) { + o.Created = func() time.Time { + return random_time_Time(f) + } + }) +} + +// Set the model columns to this value +func (m publicreportQuickMods) Comments(val string) PublicreportQuickMod { + return PublicreportQuickModFunc(func(_ context.Context, o *PublicreportQuickTemplate) { + o.Comments = func() string { return val } + }) +} + +// Set the Column from the function +func (m publicreportQuickMods) CommentsFunc(f func() string) PublicreportQuickMod { + return PublicreportQuickModFunc(func(_ context.Context, o *PublicreportQuickTemplate) { + o.Comments = f + }) +} + +// Clear any values for the column +func (m publicreportQuickMods) UnsetComments() PublicreportQuickMod { + return PublicreportQuickModFunc(func(_ context.Context, o *PublicreportQuickTemplate) { + o.Comments = nil + }) +} + +// Generates a random value for the column using the given faker +// if faker is nil, a default faker is used +func (m publicreportQuickMods) RandomComments(f *faker.Faker) PublicreportQuickMod { + return PublicreportQuickModFunc(func(_ context.Context, o *PublicreportQuickTemplate) { + o.Comments = func() string { + return random_string(f) + } + }) +} + +// Set the model columns to this value +func (m publicreportQuickMods) Location(val null.Val[string]) PublicreportQuickMod { + return PublicreportQuickModFunc(func(_ context.Context, o *PublicreportQuickTemplate) { + o.Location = func() null.Val[string] { return val } + }) +} + +// Set the Column from the function +func (m publicreportQuickMods) LocationFunc(f func() null.Val[string]) PublicreportQuickMod { + return PublicreportQuickModFunc(func(_ context.Context, o *PublicreportQuickTemplate) { + o.Location = f + }) +} + +// Clear any values for the column +func (m publicreportQuickMods) UnsetLocation() PublicreportQuickMod { + return PublicreportQuickModFunc(func(_ context.Context, o *PublicreportQuickTemplate) { + o.Location = nil + }) +} + +// Generates a random value for the column using the given faker +// if faker is nil, a default faker is used +// The generated value is sometimes null +func (m publicreportQuickMods) RandomLocation(f *faker.Faker) PublicreportQuickMod { + return PublicreportQuickModFunc(func(_ context.Context, o *PublicreportQuickTemplate) { + o.Location = func() null.Val[string] { + if f == nil { + f = &defaultFaker + } + + val := random_string(f) + return null.From(val) + } + }) +} + +// Generates a random value for the column using the given faker +// if faker is nil, a default faker is used +// The generated value is never null +func (m publicreportQuickMods) RandomLocationNotNull(f *faker.Faker) PublicreportQuickMod { + return PublicreportQuickModFunc(func(_ context.Context, o *PublicreportQuickTemplate) { + o.Location = func() null.Val[string] { + if f == nil { + f = &defaultFaker + } + + val := random_string(f) + return null.From(val) + } + }) +} + +// Set the model columns to this value +func (m publicreportQuickMods) H3cell(val null.Val[string]) PublicreportQuickMod { + return PublicreportQuickModFunc(func(_ context.Context, o *PublicreportQuickTemplate) { + o.H3cell = func() null.Val[string] { return val } + }) +} + +// Set the Column from the function +func (m publicreportQuickMods) H3cellFunc(f func() null.Val[string]) PublicreportQuickMod { + return PublicreportQuickModFunc(func(_ context.Context, o *PublicreportQuickTemplate) { + o.H3cell = f + }) +} + +// Clear any values for the column +func (m publicreportQuickMods) UnsetH3cell() PublicreportQuickMod { + return PublicreportQuickModFunc(func(_ context.Context, o *PublicreportQuickTemplate) { + o.H3cell = nil + }) +} + +// Generates a random value for the column using the given faker +// if faker is nil, a default faker is used +// The generated value is sometimes null +func (m publicreportQuickMods) RandomH3cell(f *faker.Faker) PublicreportQuickMod { + return PublicreportQuickModFunc(func(_ context.Context, o *PublicreportQuickTemplate) { + o.H3cell = func() null.Val[string] { + if f == nil { + f = &defaultFaker + } + + val := random_string(f) + return null.From(val) + } + }) +} + +// Generates a random value for the column using the given faker +// if faker is nil, a default faker is used +// The generated value is never null +func (m publicreportQuickMods) RandomH3cellNotNull(f *faker.Faker) PublicreportQuickMod { + return PublicreportQuickModFunc(func(_ context.Context, o *PublicreportQuickTemplate) { + o.H3cell = func() null.Val[string] { + if f == nil { + f = &defaultFaker + } + + val := random_string(f) + return null.From(val) + } + }) +} + +// Set the model columns to this value +func (m publicreportQuickMods) UUID(val uuid.UUID) PublicreportQuickMod { + return PublicreportQuickModFunc(func(_ context.Context, o *PublicreportQuickTemplate) { + o.UUID = func() uuid.UUID { return val } + }) +} + +// Set the Column from the function +func (m publicreportQuickMods) UUIDFunc(f func() uuid.UUID) PublicreportQuickMod { + return PublicreportQuickModFunc(func(_ context.Context, o *PublicreportQuickTemplate) { + o.UUID = f + }) +} + +// Clear any values for the column +func (m publicreportQuickMods) UnsetUUID() PublicreportQuickMod { + return PublicreportQuickModFunc(func(_ context.Context, o *PublicreportQuickTemplate) { + o.UUID = nil + }) +} + +// Generates a random value for the column using the given faker +// if faker is nil, a default faker is used +func (m publicreportQuickMods) RandomUUID(f *faker.Faker) PublicreportQuickMod { + return PublicreportQuickModFunc(func(_ context.Context, o *PublicreportQuickTemplate) { + o.UUID = func() uuid.UUID { + return random_uuid_UUID(f) + } + }) +} + +func (m publicreportQuickMods) WithParentsCascading() PublicreportQuickMod { + return PublicreportQuickModFunc(func(ctx context.Context, o *PublicreportQuickTemplate) { + if isDone, _ := publicreportQuickWithParentsCascadingCtx.Value(ctx); isDone { + return + } + ctx = publicreportQuickWithParentsCascadingCtx.WithValue(ctx, true) + }) +} + +func (m publicreportQuickMods) WithQuickPhotos(number int, related *PublicreportQuickPhotoTemplate) PublicreportQuickMod { + return PublicreportQuickModFunc(func(ctx context.Context, o *PublicreportQuickTemplate) { + o.r.QuickPhotos = []*publicreportQuickRQuickPhotosR{{ + number: number, + o: related, + }} + }) +} + +func (m publicreportQuickMods) WithNewQuickPhotos(number int, mods ...PublicreportQuickPhotoMod) PublicreportQuickMod { + return PublicreportQuickModFunc(func(ctx context.Context, o *PublicreportQuickTemplate) { + related := o.f.NewPublicreportQuickPhotoWithContext(ctx, mods...) + m.WithQuickPhotos(number, related).Apply(ctx, o) + }) +} + +func (m publicreportQuickMods) AddQuickPhotos(number int, related *PublicreportQuickPhotoTemplate) PublicreportQuickMod { + return PublicreportQuickModFunc(func(ctx context.Context, o *PublicreportQuickTemplate) { + o.r.QuickPhotos = append(o.r.QuickPhotos, &publicreportQuickRQuickPhotosR{ + number: number, + o: related, + }) + }) +} + +func (m publicreportQuickMods) AddNewQuickPhotos(number int, mods ...PublicreportQuickPhotoMod) PublicreportQuickMod { + return PublicreportQuickModFunc(func(ctx context.Context, o *PublicreportQuickTemplate) { + related := o.f.NewPublicreportQuickPhotoWithContext(ctx, mods...) + m.AddQuickPhotos(number, related).Apply(ctx, o) + }) +} + +func (m publicreportQuickMods) AddExistingQuickPhotos(existingModels ...*models.PublicreportQuickPhoto) PublicreportQuickMod { + return PublicreportQuickModFunc(func(ctx context.Context, o *PublicreportQuickTemplate) { + for _, em := range existingModels { + o.r.QuickPhotos = append(o.r.QuickPhotos, &publicreportQuickRQuickPhotosR{ + o: o.f.FromExistingPublicreportQuickPhoto(em), + }) + } + }) +} + +func (m publicreportQuickMods) WithoutQuickPhotos() PublicreportQuickMod { + return PublicreportQuickModFunc(func(ctx context.Context, o *PublicreportQuickTemplate) { + o.r.QuickPhotos = nil + }) +} diff --git a/db/factory/publicreport.quick_photo.bob.go b/db/factory/publicreport.quick_photo.bob.go new file mode 100644 index 00000000..39b70215 --- /dev/null +++ b/db/factory/publicreport.quick_photo.bob.go @@ -0,0 +1,498 @@ +// Code generated by BobGen psql v0.0.4-0.20260105020634-53e08d840e47+dirty. DO NOT EDIT. +// This file is meant to be re-generated in place and/or deleted at any time. + +package factory + +import ( + "context" + "testing" + + models "github.com/Gleipnir-Technology/nidus-sync/db/models" + "github.com/aarondl/opt/omit" + "github.com/google/uuid" + "github.com/jaswdr/faker/v2" + "github.com/stephenafamo/bob" +) + +type PublicreportQuickPhotoMod interface { + Apply(context.Context, *PublicreportQuickPhotoTemplate) +} + +type PublicreportQuickPhotoModFunc func(context.Context, *PublicreportQuickPhotoTemplate) + +func (f PublicreportQuickPhotoModFunc) Apply(ctx context.Context, n *PublicreportQuickPhotoTemplate) { + f(ctx, n) +} + +type PublicreportQuickPhotoModSlice []PublicreportQuickPhotoMod + +func (mods PublicreportQuickPhotoModSlice) Apply(ctx context.Context, n *PublicreportQuickPhotoTemplate) { + for _, f := range mods { + f.Apply(ctx, n) + } +} + +// PublicreportQuickPhotoTemplate is an object representing the database table. +// all columns are optional and should be set by mods +type PublicreportQuickPhotoTemplate struct { + ID func() int32 + Size func() int64 + Filename func() string + QuickID func() int32 + UUID func() uuid.UUID + + r publicreportQuickPhotoR + f *Factory + + alreadyPersisted bool +} + +type publicreportQuickPhotoR struct { + Quick *publicreportQuickPhotoRQuickR +} + +type publicreportQuickPhotoRQuickR struct { + o *PublicreportQuickTemplate +} + +// Apply mods to the PublicreportQuickPhotoTemplate +func (o *PublicreportQuickPhotoTemplate) Apply(ctx context.Context, mods ...PublicreportQuickPhotoMod) { + for _, mod := range mods { + mod.Apply(ctx, o) + } +} + +// setModelRels creates and sets the relationships on *models.PublicreportQuickPhoto +// according to the relationships in the template. Nothing is inserted into the db +func (t PublicreportQuickPhotoTemplate) setModelRels(o *models.PublicreportQuickPhoto) { + if t.r.Quick != nil { + rel := t.r.Quick.o.Build() + rel.R.QuickPhotos = append(rel.R.QuickPhotos, o) + o.QuickID = rel.ID // h2 + o.R.Quick = rel + } +} + +// BuildSetter returns an *models.PublicreportQuickPhotoSetter +// this does nothing with the relationship templates +func (o PublicreportQuickPhotoTemplate) BuildSetter() *models.PublicreportQuickPhotoSetter { + m := &models.PublicreportQuickPhotoSetter{} + + if o.ID != nil { + val := o.ID() + m.ID = omit.From(val) + } + if o.Size != nil { + val := o.Size() + m.Size = omit.From(val) + } + if o.Filename != nil { + val := o.Filename() + m.Filename = omit.From(val) + } + if o.QuickID != nil { + val := o.QuickID() + m.QuickID = omit.From(val) + } + if o.UUID != nil { + val := o.UUID() + m.UUID = omit.From(val) + } + + return m +} + +// BuildManySetter returns an []*models.PublicreportQuickPhotoSetter +// this does nothing with the relationship templates +func (o PublicreportQuickPhotoTemplate) BuildManySetter(number int) []*models.PublicreportQuickPhotoSetter { + m := make([]*models.PublicreportQuickPhotoSetter, number) + + for i := range m { + m[i] = o.BuildSetter() + } + + return m +} + +// Build returns an *models.PublicreportQuickPhoto +// Related objects are also created and placed in the .R field +// NOTE: Objects are not inserted into the database. Use PublicreportQuickPhotoTemplate.Create +func (o PublicreportQuickPhotoTemplate) Build() *models.PublicreportQuickPhoto { + m := &models.PublicreportQuickPhoto{} + + if o.ID != nil { + m.ID = o.ID() + } + if o.Size != nil { + m.Size = o.Size() + } + if o.Filename != nil { + m.Filename = o.Filename() + } + if o.QuickID != nil { + m.QuickID = o.QuickID() + } + if o.UUID != nil { + m.UUID = o.UUID() + } + + o.setModelRels(m) + + return m +} + +// BuildMany returns an models.PublicreportQuickPhotoSlice +// Related objects are also created and placed in the .R field +// NOTE: Objects are not inserted into the database. Use PublicreportQuickPhotoTemplate.CreateMany +func (o PublicreportQuickPhotoTemplate) BuildMany(number int) models.PublicreportQuickPhotoSlice { + m := make(models.PublicreportQuickPhotoSlice, number) + + for i := range m { + m[i] = o.Build() + } + + return m +} + +func ensureCreatablePublicreportQuickPhoto(m *models.PublicreportQuickPhotoSetter) { + if !(m.Size.IsValue()) { + val := random_int64(nil) + m.Size = omit.From(val) + } + if !(m.Filename.IsValue()) { + val := random_string(nil) + m.Filename = omit.From(val) + } + if !(m.QuickID.IsValue()) { + val := random_int32(nil) + m.QuickID = omit.From(val) + } + if !(m.UUID.IsValue()) { + val := random_uuid_UUID(nil) + m.UUID = omit.From(val) + } +} + +// insertOptRels creates and inserts any optional the relationships on *models.PublicreportQuickPhoto +// according to the relationships in the template. +// any required relationship should have already exist on the model +func (o *PublicreportQuickPhotoTemplate) insertOptRels(ctx context.Context, exec bob.Executor, m *models.PublicreportQuickPhoto) error { + var err error + + return err +} + +// Create builds a publicreportQuickPhoto and inserts it into the database +// Relations objects are also inserted and placed in the .R field +func (o *PublicreportQuickPhotoTemplate) Create(ctx context.Context, exec bob.Executor) (*models.PublicreportQuickPhoto, error) { + var err error + opt := o.BuildSetter() + ensureCreatablePublicreportQuickPhoto(opt) + + if o.r.Quick == nil { + PublicreportQuickPhotoMods.WithNewQuick().Apply(ctx, o) + } + + var rel0 *models.PublicreportQuick + + if o.r.Quick.o.alreadyPersisted { + rel0 = o.r.Quick.o.Build() + } else { + rel0, err = o.r.Quick.o.Create(ctx, exec) + if err != nil { + return nil, err + } + } + + opt.QuickID = omit.From(rel0.ID) + + m, err := models.PublicreportQuickPhotos.Insert(opt).One(ctx, exec) + if err != nil { + return nil, err + } + + m.R.Quick = rel0 + + if err := o.insertOptRels(ctx, exec, m); err != nil { + return nil, err + } + return m, err +} + +// MustCreate builds a publicreportQuickPhoto and inserts it into the database +// Relations objects are also inserted and placed in the .R field +// panics if an error occurs +func (o *PublicreportQuickPhotoTemplate) MustCreate(ctx context.Context, exec bob.Executor) *models.PublicreportQuickPhoto { + m, err := o.Create(ctx, exec) + if err != nil { + panic(err) + } + return m +} + +// CreateOrFail builds a publicreportQuickPhoto and inserts it into the database +// Relations objects are also inserted and placed in the .R field +// It calls `tb.Fatal(err)` on the test/benchmark if an error occurs +func (o *PublicreportQuickPhotoTemplate) CreateOrFail(ctx context.Context, tb testing.TB, exec bob.Executor) *models.PublicreportQuickPhoto { + tb.Helper() + m, err := o.Create(ctx, exec) + if err != nil { + tb.Fatal(err) + return nil + } + return m +} + +// CreateMany builds multiple publicreportQuickPhotos and inserts them into the database +// Relations objects are also inserted and placed in the .R field +func (o PublicreportQuickPhotoTemplate) CreateMany(ctx context.Context, exec bob.Executor, number int) (models.PublicreportQuickPhotoSlice, error) { + var err error + m := make(models.PublicreportQuickPhotoSlice, number) + + for i := range m { + m[i], err = o.Create(ctx, exec) + if err != nil { + return nil, err + } + } + + return m, nil +} + +// MustCreateMany builds multiple publicreportQuickPhotos and inserts them into the database +// Relations objects are also inserted and placed in the .R field +// panics if an error occurs +func (o PublicreportQuickPhotoTemplate) MustCreateMany(ctx context.Context, exec bob.Executor, number int) models.PublicreportQuickPhotoSlice { + m, err := o.CreateMany(ctx, exec, number) + if err != nil { + panic(err) + } + return m +} + +// CreateManyOrFail builds multiple publicreportQuickPhotos and inserts them into the database +// Relations objects are also inserted and placed in the .R field +// It calls `tb.Fatal(err)` on the test/benchmark if an error occurs +func (o PublicreportQuickPhotoTemplate) CreateManyOrFail(ctx context.Context, tb testing.TB, exec bob.Executor, number int) models.PublicreportQuickPhotoSlice { + tb.Helper() + m, err := o.CreateMany(ctx, exec, number) + if err != nil { + tb.Fatal(err) + return nil + } + return m +} + +// PublicreportQuickPhoto has methods that act as mods for the PublicreportQuickPhotoTemplate +var PublicreportQuickPhotoMods publicreportQuickPhotoMods + +type publicreportQuickPhotoMods struct{} + +func (m publicreportQuickPhotoMods) RandomizeAllColumns(f *faker.Faker) PublicreportQuickPhotoMod { + return PublicreportQuickPhotoModSlice{ + PublicreportQuickPhotoMods.RandomID(f), + PublicreportQuickPhotoMods.RandomSize(f), + PublicreportQuickPhotoMods.RandomFilename(f), + PublicreportQuickPhotoMods.RandomQuickID(f), + PublicreportQuickPhotoMods.RandomUUID(f), + } +} + +// Set the model columns to this value +func (m publicreportQuickPhotoMods) ID(val int32) PublicreportQuickPhotoMod { + return PublicreportQuickPhotoModFunc(func(_ context.Context, o *PublicreportQuickPhotoTemplate) { + o.ID = func() int32 { return val } + }) +} + +// Set the Column from the function +func (m publicreportQuickPhotoMods) IDFunc(f func() int32) PublicreportQuickPhotoMod { + return PublicreportQuickPhotoModFunc(func(_ context.Context, o *PublicreportQuickPhotoTemplate) { + o.ID = f + }) +} + +// Clear any values for the column +func (m publicreportQuickPhotoMods) UnsetID() PublicreportQuickPhotoMod { + return PublicreportQuickPhotoModFunc(func(_ context.Context, o *PublicreportQuickPhotoTemplate) { + o.ID = nil + }) +} + +// Generates a random value for the column using the given faker +// if faker is nil, a default faker is used +func (m publicreportQuickPhotoMods) RandomID(f *faker.Faker) PublicreportQuickPhotoMod { + return PublicreportQuickPhotoModFunc(func(_ context.Context, o *PublicreportQuickPhotoTemplate) { + o.ID = func() int32 { + return random_int32(f) + } + }) +} + +// Set the model columns to this value +func (m publicreportQuickPhotoMods) Size(val int64) PublicreportQuickPhotoMod { + return PublicreportQuickPhotoModFunc(func(_ context.Context, o *PublicreportQuickPhotoTemplate) { + o.Size = func() int64 { return val } + }) +} + +// Set the Column from the function +func (m publicreportQuickPhotoMods) SizeFunc(f func() int64) PublicreportQuickPhotoMod { + return PublicreportQuickPhotoModFunc(func(_ context.Context, o *PublicreportQuickPhotoTemplate) { + o.Size = f + }) +} + +// Clear any values for the column +func (m publicreportQuickPhotoMods) UnsetSize() PublicreportQuickPhotoMod { + return PublicreportQuickPhotoModFunc(func(_ context.Context, o *PublicreportQuickPhotoTemplate) { + o.Size = nil + }) +} + +// Generates a random value for the column using the given faker +// if faker is nil, a default faker is used +func (m publicreportQuickPhotoMods) RandomSize(f *faker.Faker) PublicreportQuickPhotoMod { + return PublicreportQuickPhotoModFunc(func(_ context.Context, o *PublicreportQuickPhotoTemplate) { + o.Size = func() int64 { + return random_int64(f) + } + }) +} + +// Set the model columns to this value +func (m publicreportQuickPhotoMods) Filename(val string) PublicreportQuickPhotoMod { + return PublicreportQuickPhotoModFunc(func(_ context.Context, o *PublicreportQuickPhotoTemplate) { + o.Filename = func() string { return val } + }) +} + +// Set the Column from the function +func (m publicreportQuickPhotoMods) FilenameFunc(f func() string) PublicreportQuickPhotoMod { + return PublicreportQuickPhotoModFunc(func(_ context.Context, o *PublicreportQuickPhotoTemplate) { + o.Filename = f + }) +} + +// Clear any values for the column +func (m publicreportQuickPhotoMods) UnsetFilename() PublicreportQuickPhotoMod { + return PublicreportQuickPhotoModFunc(func(_ context.Context, o *PublicreportQuickPhotoTemplate) { + o.Filename = nil + }) +} + +// Generates a random value for the column using the given faker +// if faker is nil, a default faker is used +func (m publicreportQuickPhotoMods) RandomFilename(f *faker.Faker) PublicreportQuickPhotoMod { + return PublicreportQuickPhotoModFunc(func(_ context.Context, o *PublicreportQuickPhotoTemplate) { + o.Filename = func() string { + return random_string(f) + } + }) +} + +// Set the model columns to this value +func (m publicreportQuickPhotoMods) QuickID(val int32) PublicreportQuickPhotoMod { + return PublicreportQuickPhotoModFunc(func(_ context.Context, o *PublicreportQuickPhotoTemplate) { + o.QuickID = func() int32 { return val } + }) +} + +// Set the Column from the function +func (m publicreportQuickPhotoMods) QuickIDFunc(f func() int32) PublicreportQuickPhotoMod { + return PublicreportQuickPhotoModFunc(func(_ context.Context, o *PublicreportQuickPhotoTemplate) { + o.QuickID = f + }) +} + +// Clear any values for the column +func (m publicreportQuickPhotoMods) UnsetQuickID() PublicreportQuickPhotoMod { + return PublicreportQuickPhotoModFunc(func(_ context.Context, o *PublicreportQuickPhotoTemplate) { + o.QuickID = nil + }) +} + +// Generates a random value for the column using the given faker +// if faker is nil, a default faker is used +func (m publicreportQuickPhotoMods) RandomQuickID(f *faker.Faker) PublicreportQuickPhotoMod { + return PublicreportQuickPhotoModFunc(func(_ context.Context, o *PublicreportQuickPhotoTemplate) { + o.QuickID = func() int32 { + return random_int32(f) + } + }) +} + +// Set the model columns to this value +func (m publicreportQuickPhotoMods) UUID(val uuid.UUID) PublicreportQuickPhotoMod { + return PublicreportQuickPhotoModFunc(func(_ context.Context, o *PublicreportQuickPhotoTemplate) { + o.UUID = func() uuid.UUID { return val } + }) +} + +// Set the Column from the function +func (m publicreportQuickPhotoMods) UUIDFunc(f func() uuid.UUID) PublicreportQuickPhotoMod { + return PublicreportQuickPhotoModFunc(func(_ context.Context, o *PublicreportQuickPhotoTemplate) { + o.UUID = f + }) +} + +// Clear any values for the column +func (m publicreportQuickPhotoMods) UnsetUUID() PublicreportQuickPhotoMod { + return PublicreportQuickPhotoModFunc(func(_ context.Context, o *PublicreportQuickPhotoTemplate) { + o.UUID = nil + }) +} + +// Generates a random value for the column using the given faker +// if faker is nil, a default faker is used +func (m publicreportQuickPhotoMods) RandomUUID(f *faker.Faker) PublicreportQuickPhotoMod { + return PublicreportQuickPhotoModFunc(func(_ context.Context, o *PublicreportQuickPhotoTemplate) { + o.UUID = func() uuid.UUID { + return random_uuid_UUID(f) + } + }) +} + +func (m publicreportQuickPhotoMods) WithParentsCascading() PublicreportQuickPhotoMod { + return PublicreportQuickPhotoModFunc(func(ctx context.Context, o *PublicreportQuickPhotoTemplate) { + if isDone, _ := publicreportQuickPhotoWithParentsCascadingCtx.Value(ctx); isDone { + return + } + ctx = publicreportQuickPhotoWithParentsCascadingCtx.WithValue(ctx, true) + { + + related := o.f.NewPublicreportQuickWithContext(ctx, PublicreportQuickMods.WithParentsCascading()) + m.WithQuick(related).Apply(ctx, o) + } + }) +} + +func (m publicreportQuickPhotoMods) WithQuick(rel *PublicreportQuickTemplate) PublicreportQuickPhotoMod { + return PublicreportQuickPhotoModFunc(func(ctx context.Context, o *PublicreportQuickPhotoTemplate) { + o.r.Quick = &publicreportQuickPhotoRQuickR{ + o: rel, + } + }) +} + +func (m publicreportQuickPhotoMods) WithNewQuick(mods ...PublicreportQuickMod) PublicreportQuickPhotoMod { + return PublicreportQuickPhotoModFunc(func(ctx context.Context, o *PublicreportQuickPhotoTemplate) { + related := o.f.NewPublicreportQuickWithContext(ctx, mods...) + + m.WithQuick(related).Apply(ctx, o) + }) +} + +func (m publicreportQuickPhotoMods) WithExistingQuick(em *models.PublicreportQuick) PublicreportQuickPhotoMod { + return PublicreportQuickPhotoModFunc(func(ctx context.Context, o *PublicreportQuickPhotoTemplate) { + o.r.Quick = &publicreportQuickPhotoRQuickR{ + o: o.f.FromExistingPublicreportQuick(em), + } + }) +} + +func (m publicreportQuickPhotoMods) WithoutQuick() PublicreportQuickPhotoMod { + return PublicreportQuickPhotoModFunc(func(ctx context.Context, o *PublicreportQuickPhotoTemplate) { + o.r.Quick = nil + }) +} diff --git a/db/migrations/00024_public_report.sql b/db/migrations/00024_public_report.sql new file mode 100644 index 00000000..d4429820 --- /dev/null +++ b/db/migrations/00024_public_report.sql @@ -0,0 +1,24 @@ +-- +goose Up +CREATE SCHEMA IF NOT EXISTS publicreport; +CREATE TABLE publicreport.quick ( + id SERIAL PRIMARY KEY, + created TIMESTAMP WITHOUT TIME ZONE NOT NULL, + comments TEXT NOT NULL, + location GEOGRAPHY, + h3cell h3index, + uuid UUID NOT NULL +); + +CREATE TABLE publicreport.quick_photo ( + id SERIAL PRIMARY KEY, + size BIGINT NOT NULL, + filename TEXT NOT NULL, + quick_id INT NOT NULL REFERENCES publicreport.quick(id), + uuid UUID NOT NULL +); + +-- +goose Down +DROP TABLE publicreport.quick_photo; +DROP TABLE publicreport.quick; +DROP SCHEMA publicreport; + diff --git a/db/models/bob_joins.bob.go b/db/models/bob_joins.bob.go index 59b0879e..6965dcd3 100644 --- a/db/models/bob_joins.bob.go +++ b/db/models/bob_joins.bob.go @@ -70,6 +70,8 @@ type joins[Q dialect.Joinable] struct { Notifications joinSet[notificationJoins[Q]] OauthTokens joinSet[oauthTokenJoins[Q]] Organizations joinSet[organizationJoins[Q]] + PublicreportQuicks joinSet[publicreportQuickJoins[Q]] + PublicreportQuickPhotos joinSet[publicreportQuickPhotoJoins[Q]] Users joinSet[userJoins[Q]] } @@ -121,6 +123,8 @@ func getJoins[Q dialect.Joinable]() joins[Q] { Notifications: buildJoinSet[notificationJoins[Q]](Notifications.Columns, buildNotificationJoins), OauthTokens: buildJoinSet[oauthTokenJoins[Q]](OauthTokens.Columns, buildOauthTokenJoins), Organizations: buildJoinSet[organizationJoins[Q]](Organizations.Columns, buildOrganizationJoins), + PublicreportQuicks: buildJoinSet[publicreportQuickJoins[Q]](PublicreportQuicks.Columns, buildPublicreportQuickJoins), + PublicreportQuickPhotos: buildJoinSet[publicreportQuickPhotoJoins[Q]](PublicreportQuickPhotos.Columns, buildPublicreportQuickPhotoJoins), Users: buildJoinSet[userJoins[Q]](Users.Columns, buildUserJoins), } } diff --git a/db/models/bob_loaders.bob.go b/db/models/bob_loaders.bob.go index eaeee752..98764377 100644 --- a/db/models/bob_loaders.bob.go +++ b/db/models/bob_loaders.bob.go @@ -55,6 +55,8 @@ type preloaders struct { Notification notificationPreloader OauthToken oauthTokenPreloader Organization organizationPreloader + PublicreportQuick publicreportQuickPreloader + PublicreportQuickPhoto publicreportQuickPhotoPreloader User userPreloader } @@ -98,6 +100,8 @@ func getPreloaders() preloaders { Notification: buildNotificationPreloader(), OauthToken: buildOauthTokenPreloader(), Organization: buildOrganizationPreloader(), + PublicreportQuick: buildPublicreportQuickPreloader(), + PublicreportQuickPhoto: buildPublicreportQuickPhotoPreloader(), User: buildUserPreloader(), } } @@ -147,6 +151,8 @@ type thenLoaders[Q orm.Loadable] struct { Notification notificationThenLoader[Q] OauthToken oauthTokenThenLoader[Q] Organization organizationThenLoader[Q] + PublicreportQuick publicreportQuickThenLoader[Q] + PublicreportQuickPhoto publicreportQuickPhotoThenLoader[Q] User userThenLoader[Q] } @@ -190,6 +196,8 @@ func getThenLoaders[Q orm.Loadable]() thenLoaders[Q] { Notification: buildNotificationThenLoader[Q](), OauthToken: buildOauthTokenThenLoader[Q](), Organization: buildOrganizationThenLoader[Q](), + PublicreportQuick: buildPublicreportQuickThenLoader[Q](), + PublicreportQuickPhoto: buildPublicreportQuickPhotoThenLoader[Q](), User: buildUserThenLoader[Q](), } } diff --git a/db/models/bob_types.bob_test.go b/db/models/bob_types.bob_test.go index 44172283..71e366b6 100644 --- a/db/models/bob_types.bob_test.go +++ b/db/models/bob_types.bob_test.go @@ -141,6 +141,12 @@ var _ bob.HookableType = &OauthToken{} // Make sure the type Organization runs hooks after queries var _ bob.HookableType = &Organization{} +// Make sure the type PublicreportQuick runs hooks after queries +var _ bob.HookableType = &PublicreportQuick{} + +// Make sure the type PublicreportQuickPhoto runs hooks after queries +var _ bob.HookableType = &PublicreportQuickPhoto{} + // Make sure the type RasterColumn runs hooks after queries var _ bob.HookableType = &RasterColumn{} diff --git a/db/models/bob_where.bob.go b/db/models/bob_where.bob.go index 3f81d91a..9b596bb1 100644 --- a/db/models/bob_where.bob.go +++ b/db/models/bob_where.bob.go @@ -58,6 +58,8 @@ func Where[Q psql.Filterable]() struct { Notifications notificationWhere[Q] OauthTokens oauthTokenWhere[Q] Organizations organizationWhere[Q] + PublicreportQuicks publicreportQuickWhere[Q] + PublicreportQuickPhotos publicreportQuickPhotoWhere[Q] RasterColumns rasterColumnWhere[Q] RasterOverviews rasterOverviewWhere[Q] Sessions sessionWhere[Q] @@ -106,6 +108,8 @@ func Where[Q psql.Filterable]() struct { Notifications notificationWhere[Q] OauthTokens oauthTokenWhere[Q] Organizations organizationWhere[Q] + PublicreportQuicks publicreportQuickWhere[Q] + PublicreportQuickPhotos publicreportQuickPhotoWhere[Q] RasterColumns rasterColumnWhere[Q] RasterOverviews rasterOverviewWhere[Q] Sessions sessionWhere[Q] @@ -153,6 +157,8 @@ func Where[Q psql.Filterable]() struct { Notifications: buildNotificationWhere[Q](Notifications.Columns), OauthTokens: buildOauthTokenWhere[Q](OauthTokens.Columns), Organizations: buildOrganizationWhere[Q](Organizations.Columns), + PublicreportQuicks: buildPublicreportQuickWhere[Q](PublicreportQuicks.Columns), + PublicreportQuickPhotos: buildPublicreportQuickPhotoWhere[Q](PublicreportQuickPhotos.Columns), RasterColumns: buildRasterColumnWhere[Q](RasterColumns.Columns), RasterOverviews: buildRasterOverviewWhere[Q](RasterOverviews.Columns), Sessions: buildSessionWhere[Q](Sessions.Columns), diff --git a/db/models/publicreport.quick.bob.go b/db/models/publicreport.quick.bob.go new file mode 100644 index 00000000..612883e2 --- /dev/null +++ b/db/models/publicreport.quick.bob.go @@ -0,0 +1,721 @@ +// Code generated by BobGen psql v0.0.4-0.20260105020634-53e08d840e47+dirty. DO NOT EDIT. +// This file is meant to be re-generated in place and/or deleted at any time. + +package models + +import ( + "context" + "fmt" + "io" + "time" + + "github.com/aarondl/opt/null" + "github.com/aarondl/opt/omit" + "github.com/aarondl/opt/omitnull" + "github.com/google/uuid" + "github.com/stephenafamo/bob" + "github.com/stephenafamo/bob/dialect/psql" + "github.com/stephenafamo/bob/dialect/psql/dialect" + "github.com/stephenafamo/bob/dialect/psql/dm" + "github.com/stephenafamo/bob/dialect/psql/sm" + "github.com/stephenafamo/bob/dialect/psql/um" + "github.com/stephenafamo/bob/expr" + "github.com/stephenafamo/bob/mods" + "github.com/stephenafamo/bob/orm" + "github.com/stephenafamo/bob/types/pgtypes" +) + +// PublicreportQuick is an object representing the database table. +type PublicreportQuick struct { + ID int32 `db:"id,pk" ` + Created time.Time `db:"created" ` + Comments string `db:"comments" ` + Location null.Val[string] `db:"location" ` + H3cell null.Val[string] `db:"h3cell" ` + UUID uuid.UUID `db:"uuid" ` + + R publicreportQuickR `db:"-" ` +} + +// PublicreportQuickSlice is an alias for a slice of pointers to PublicreportQuick. +// This should almost always be used instead of []*PublicreportQuick. +type PublicreportQuickSlice []*PublicreportQuick + +// PublicreportQuicks contains methods to work with the quick table +var PublicreportQuicks = psql.NewTablex[*PublicreportQuick, PublicreportQuickSlice, *PublicreportQuickSetter]("publicreport", "quick", buildPublicreportQuickColumns("publicreport.quick")) + +// PublicreportQuicksQuery is a query on the quick table +type PublicreportQuicksQuery = *psql.ViewQuery[*PublicreportQuick, PublicreportQuickSlice] + +// publicreportQuickR is where relationships are stored. +type publicreportQuickR struct { + QuickPhotos PublicreportQuickPhotoSlice // publicreport.quick_photo.quick_photo_quick_id_fkey +} + +func buildPublicreportQuickColumns(alias string) publicreportQuickColumns { + return publicreportQuickColumns{ + ColumnsExpr: expr.NewColumnsExpr( + "id", "created", "comments", "location", "h3cell", "uuid", + ).WithParent("publicreport.quick"), + tableAlias: alias, + ID: psql.Quote(alias, "id"), + Created: psql.Quote(alias, "created"), + Comments: psql.Quote(alias, "comments"), + Location: psql.Quote(alias, "location"), + H3cell: psql.Quote(alias, "h3cell"), + UUID: psql.Quote(alias, "uuid"), + } +} + +type publicreportQuickColumns struct { + expr.ColumnsExpr + tableAlias string + ID psql.Expression + Created psql.Expression + Comments psql.Expression + Location psql.Expression + H3cell psql.Expression + UUID psql.Expression +} + +func (c publicreportQuickColumns) Alias() string { + return c.tableAlias +} + +func (publicreportQuickColumns) AliasedAs(alias string) publicreportQuickColumns { + return buildPublicreportQuickColumns(alias) +} + +// PublicreportQuickSetter is used for insert/upsert/update operations +// All values are optional, and do not have to be set +// Generated columns are not included +type PublicreportQuickSetter struct { + ID omit.Val[int32] `db:"id,pk" ` + Created omit.Val[time.Time] `db:"created" ` + Comments omit.Val[string] `db:"comments" ` + Location omitnull.Val[string] `db:"location" ` + H3cell omitnull.Val[string] `db:"h3cell" ` + UUID omit.Val[uuid.UUID] `db:"uuid" ` +} + +func (s PublicreportQuickSetter) SetColumns() []string { + vals := make([]string, 0, 6) + if s.ID.IsValue() { + vals = append(vals, "id") + } + if s.Created.IsValue() { + vals = append(vals, "created") + } + if s.Comments.IsValue() { + vals = append(vals, "comments") + } + if !s.Location.IsUnset() { + vals = append(vals, "location") + } + if !s.H3cell.IsUnset() { + vals = append(vals, "h3cell") + } + if s.UUID.IsValue() { + vals = append(vals, "uuid") + } + return vals +} + +func (s PublicreportQuickSetter) Overwrite(t *PublicreportQuick) { + if s.ID.IsValue() { + t.ID = s.ID.MustGet() + } + if s.Created.IsValue() { + t.Created = s.Created.MustGet() + } + if s.Comments.IsValue() { + t.Comments = s.Comments.MustGet() + } + if !s.Location.IsUnset() { + t.Location = s.Location.MustGetNull() + } + if !s.H3cell.IsUnset() { + t.H3cell = s.H3cell.MustGetNull() + } + if s.UUID.IsValue() { + t.UUID = s.UUID.MustGet() + } +} + +func (s *PublicreportQuickSetter) Apply(q *dialect.InsertQuery) { + q.AppendHooks(func(ctx context.Context, exec bob.Executor) (context.Context, error) { + return PublicreportQuicks.BeforeInsertHooks.RunHooks(ctx, exec, s) + }) + + q.AppendValues(bob.ExpressionFunc(func(ctx context.Context, w io.StringWriter, d bob.Dialect, start int) ([]any, error) { + vals := make([]bob.Expression, 6) + if s.ID.IsValue() { + vals[0] = psql.Arg(s.ID.MustGet()) + } else { + vals[0] = psql.Raw("DEFAULT") + } + + if s.Created.IsValue() { + vals[1] = psql.Arg(s.Created.MustGet()) + } else { + vals[1] = psql.Raw("DEFAULT") + } + + if s.Comments.IsValue() { + vals[2] = psql.Arg(s.Comments.MustGet()) + } else { + vals[2] = psql.Raw("DEFAULT") + } + + if !s.Location.IsUnset() { + vals[3] = psql.Arg(s.Location.MustGetNull()) + } else { + vals[3] = psql.Raw("DEFAULT") + } + + if !s.H3cell.IsUnset() { + vals[4] = psql.Arg(s.H3cell.MustGetNull()) + } else { + vals[4] = psql.Raw("DEFAULT") + } + + if s.UUID.IsValue() { + vals[5] = psql.Arg(s.UUID.MustGet()) + } else { + vals[5] = psql.Raw("DEFAULT") + } + + return bob.ExpressSlice(ctx, w, d, start, vals, "", ", ", "") + })) +} + +func (s PublicreportQuickSetter) UpdateMod() bob.Mod[*dialect.UpdateQuery] { + return um.Set(s.Expressions()...) +} + +func (s PublicreportQuickSetter) Expressions(prefix ...string) []bob.Expression { + exprs := make([]bob.Expression, 0, 6) + + if s.ID.IsValue() { + exprs = append(exprs, expr.Join{Sep: " = ", Exprs: []bob.Expression{ + psql.Quote(append(prefix, "id")...), + psql.Arg(s.ID), + }}) + } + + if s.Created.IsValue() { + exprs = append(exprs, expr.Join{Sep: " = ", Exprs: []bob.Expression{ + psql.Quote(append(prefix, "created")...), + psql.Arg(s.Created), + }}) + } + + if s.Comments.IsValue() { + exprs = append(exprs, expr.Join{Sep: " = ", Exprs: []bob.Expression{ + psql.Quote(append(prefix, "comments")...), + psql.Arg(s.Comments), + }}) + } + + if !s.Location.IsUnset() { + exprs = append(exprs, expr.Join{Sep: " = ", Exprs: []bob.Expression{ + psql.Quote(append(prefix, "location")...), + psql.Arg(s.Location), + }}) + } + + if !s.H3cell.IsUnset() { + exprs = append(exprs, expr.Join{Sep: " = ", Exprs: []bob.Expression{ + psql.Quote(append(prefix, "h3cell")...), + psql.Arg(s.H3cell), + }}) + } + + if s.UUID.IsValue() { + exprs = append(exprs, expr.Join{Sep: " = ", Exprs: []bob.Expression{ + psql.Quote(append(prefix, "uuid")...), + psql.Arg(s.UUID), + }}) + } + + return exprs +} + +// FindPublicreportQuick retrieves a single record by primary key +// If cols is empty Find will return all columns. +func FindPublicreportQuick(ctx context.Context, exec bob.Executor, IDPK int32, cols ...string) (*PublicreportQuick, error) { + if len(cols) == 0 { + return PublicreportQuicks.Query( + sm.Where(PublicreportQuicks.Columns.ID.EQ(psql.Arg(IDPK))), + ).One(ctx, exec) + } + + return PublicreportQuicks.Query( + sm.Where(PublicreportQuicks.Columns.ID.EQ(psql.Arg(IDPK))), + sm.Columns(PublicreportQuicks.Columns.Only(cols...)), + ).One(ctx, exec) +} + +// PublicreportQuickExists checks the presence of a single record by primary key +func PublicreportQuickExists(ctx context.Context, exec bob.Executor, IDPK int32) (bool, error) { + return PublicreportQuicks.Query( + sm.Where(PublicreportQuicks.Columns.ID.EQ(psql.Arg(IDPK))), + ).Exists(ctx, exec) +} + +// AfterQueryHook is called after PublicreportQuick is retrieved from the database +func (o *PublicreportQuick) AfterQueryHook(ctx context.Context, exec bob.Executor, queryType bob.QueryType) error { + var err error + + switch queryType { + case bob.QueryTypeSelect: + ctx, err = PublicreportQuicks.AfterSelectHooks.RunHooks(ctx, exec, PublicreportQuickSlice{o}) + case bob.QueryTypeInsert: + ctx, err = PublicreportQuicks.AfterInsertHooks.RunHooks(ctx, exec, PublicreportQuickSlice{o}) + case bob.QueryTypeUpdate: + ctx, err = PublicreportQuicks.AfterUpdateHooks.RunHooks(ctx, exec, PublicreportQuickSlice{o}) + case bob.QueryTypeDelete: + ctx, err = PublicreportQuicks.AfterDeleteHooks.RunHooks(ctx, exec, PublicreportQuickSlice{o}) + } + + return err +} + +// primaryKeyVals returns the primary key values of the PublicreportQuick +func (o *PublicreportQuick) primaryKeyVals() bob.Expression { + return psql.Arg(o.ID) +} + +func (o *PublicreportQuick) pkEQ() dialect.Expression { + return psql.Quote("publicreport.quick", "id").EQ(bob.ExpressionFunc(func(ctx context.Context, w io.StringWriter, d bob.Dialect, start int) ([]any, error) { + return o.primaryKeyVals().WriteSQL(ctx, w, d, start) + })) +} + +// Update uses an executor to update the PublicreportQuick +func (o *PublicreportQuick) Update(ctx context.Context, exec bob.Executor, s *PublicreportQuickSetter) error { + v, err := PublicreportQuicks.Update(s.UpdateMod(), um.Where(o.pkEQ())).One(ctx, exec) + if err != nil { + return err + } + + o.R = v.R + *o = *v + + return nil +} + +// Delete deletes a single PublicreportQuick record with an executor +func (o *PublicreportQuick) Delete(ctx context.Context, exec bob.Executor) error { + _, err := PublicreportQuicks.Delete(dm.Where(o.pkEQ())).Exec(ctx, exec) + return err +} + +// Reload refreshes the PublicreportQuick using the executor +func (o *PublicreportQuick) Reload(ctx context.Context, exec bob.Executor) error { + o2, err := PublicreportQuicks.Query( + sm.Where(PublicreportQuicks.Columns.ID.EQ(psql.Arg(o.ID))), + ).One(ctx, exec) + if err != nil { + return err + } + o2.R = o.R + *o = *o2 + + return nil +} + +// AfterQueryHook is called after PublicreportQuickSlice is retrieved from the database +func (o PublicreportQuickSlice) AfterQueryHook(ctx context.Context, exec bob.Executor, queryType bob.QueryType) error { + var err error + + switch queryType { + case bob.QueryTypeSelect: + ctx, err = PublicreportQuicks.AfterSelectHooks.RunHooks(ctx, exec, o) + case bob.QueryTypeInsert: + ctx, err = PublicreportQuicks.AfterInsertHooks.RunHooks(ctx, exec, o) + case bob.QueryTypeUpdate: + ctx, err = PublicreportQuicks.AfterUpdateHooks.RunHooks(ctx, exec, o) + case bob.QueryTypeDelete: + ctx, err = PublicreportQuicks.AfterDeleteHooks.RunHooks(ctx, exec, o) + } + + return err +} + +func (o PublicreportQuickSlice) pkIN() dialect.Expression { + if len(o) == 0 { + return psql.Raw("NULL") + } + + return psql.Quote("publicreport.quick", "id").In(bob.ExpressionFunc(func(ctx context.Context, w io.StringWriter, d bob.Dialect, start int) ([]any, error) { + pkPairs := make([]bob.Expression, len(o)) + for i, row := range o { + pkPairs[i] = row.primaryKeyVals() + } + return bob.ExpressSlice(ctx, w, d, start, pkPairs, "", ", ", "") + })) +} + +// copyMatchingRows finds models in the given slice that have the same primary key +// then it first copies the existing relationships from the old model to the new model +// and then replaces the old model in the slice with the new model +func (o PublicreportQuickSlice) copyMatchingRows(from ...*PublicreportQuick) { + for i, old := range o { + for _, new := range from { + if new.ID != old.ID { + continue + } + new.R = old.R + o[i] = new + break + } + } +} + +// UpdateMod modifies an update query with "WHERE primary_key IN (o...)" +func (o PublicreportQuickSlice) UpdateMod() bob.Mod[*dialect.UpdateQuery] { + return bob.ModFunc[*dialect.UpdateQuery](func(q *dialect.UpdateQuery) { + q.AppendHooks(func(ctx context.Context, exec bob.Executor) (context.Context, error) { + return PublicreportQuicks.BeforeUpdateHooks.RunHooks(ctx, exec, o) + }) + + q.AppendLoader(bob.LoaderFunc(func(ctx context.Context, exec bob.Executor, retrieved any) error { + var err error + switch retrieved := retrieved.(type) { + case *PublicreportQuick: + o.copyMatchingRows(retrieved) + case []*PublicreportQuick: + o.copyMatchingRows(retrieved...) + case PublicreportQuickSlice: + o.copyMatchingRows(retrieved...) + default: + // If the retrieved value is not a PublicreportQuick or a slice of PublicreportQuick + // then run the AfterUpdateHooks on the slice + _, err = PublicreportQuicks.AfterUpdateHooks.RunHooks(ctx, exec, o) + } + + return err + })) + + q.AppendWhere(o.pkIN()) + }) +} + +// DeleteMod modifies an delete query with "WHERE primary_key IN (o...)" +func (o PublicreportQuickSlice) DeleteMod() bob.Mod[*dialect.DeleteQuery] { + return bob.ModFunc[*dialect.DeleteQuery](func(q *dialect.DeleteQuery) { + q.AppendHooks(func(ctx context.Context, exec bob.Executor) (context.Context, error) { + return PublicreportQuicks.BeforeDeleteHooks.RunHooks(ctx, exec, o) + }) + + q.AppendLoader(bob.LoaderFunc(func(ctx context.Context, exec bob.Executor, retrieved any) error { + var err error + switch retrieved := retrieved.(type) { + case *PublicreportQuick: + o.copyMatchingRows(retrieved) + case []*PublicreportQuick: + o.copyMatchingRows(retrieved...) + case PublicreportQuickSlice: + o.copyMatchingRows(retrieved...) + default: + // If the retrieved value is not a PublicreportQuick or a slice of PublicreportQuick + // then run the AfterDeleteHooks on the slice + _, err = PublicreportQuicks.AfterDeleteHooks.RunHooks(ctx, exec, o) + } + + return err + })) + + q.AppendWhere(o.pkIN()) + }) +} + +func (o PublicreportQuickSlice) UpdateAll(ctx context.Context, exec bob.Executor, vals PublicreportQuickSetter) error { + if len(o) == 0 { + return nil + } + + _, err := PublicreportQuicks.Update(vals.UpdateMod(), o.UpdateMod()).All(ctx, exec) + return err +} + +func (o PublicreportQuickSlice) DeleteAll(ctx context.Context, exec bob.Executor) error { + if len(o) == 0 { + return nil + } + + _, err := PublicreportQuicks.Delete(o.DeleteMod()).Exec(ctx, exec) + return err +} + +func (o PublicreportQuickSlice) ReloadAll(ctx context.Context, exec bob.Executor) error { + if len(o) == 0 { + return nil + } + + o2, err := PublicreportQuicks.Query(sm.Where(o.pkIN())).All(ctx, exec) + if err != nil { + return err + } + + o.copyMatchingRows(o2...) + + return nil +} + +// QuickPhotos starts a query for related objects on publicreport.quick_photo +func (o *PublicreportQuick) QuickPhotos(mods ...bob.Mod[*dialect.SelectQuery]) PublicreportQuickPhotosQuery { + return PublicreportQuickPhotos.Query(append(mods, + sm.Where(PublicreportQuickPhotos.Columns.QuickID.EQ(psql.Arg(o.ID))), + )...) +} + +func (os PublicreportQuickSlice) QuickPhotos(mods ...bob.Mod[*dialect.SelectQuery]) PublicreportQuickPhotosQuery { + 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 PublicreportQuickPhotos.Query(append(mods, + sm.Where(psql.Group(PublicreportQuickPhotos.Columns.QuickID).OP("IN", PKArgExpr)), + )...) +} + +func insertPublicreportQuickQuickPhotos0(ctx context.Context, exec bob.Executor, publicreportQuickPhotos1 []*PublicreportQuickPhotoSetter, publicreportQuick0 *PublicreportQuick) (PublicreportQuickPhotoSlice, error) { + for i := range publicreportQuickPhotos1 { + publicreportQuickPhotos1[i].QuickID = omit.From(publicreportQuick0.ID) + } + + ret, err := PublicreportQuickPhotos.Insert(bob.ToMods(publicreportQuickPhotos1...)).All(ctx, exec) + if err != nil { + return ret, fmt.Errorf("insertPublicreportQuickQuickPhotos0: %w", err) + } + + return ret, nil +} + +func attachPublicreportQuickQuickPhotos0(ctx context.Context, exec bob.Executor, count int, publicreportQuickPhotos1 PublicreportQuickPhotoSlice, publicreportQuick0 *PublicreportQuick) (PublicreportQuickPhotoSlice, error) { + setter := &PublicreportQuickPhotoSetter{ + QuickID: omit.From(publicreportQuick0.ID), + } + + err := publicreportQuickPhotos1.UpdateAll(ctx, exec, *setter) + if err != nil { + return nil, fmt.Errorf("attachPublicreportQuickQuickPhotos0: %w", err) + } + + return publicreportQuickPhotos1, nil +} + +func (publicreportQuick0 *PublicreportQuick) InsertQuickPhotos(ctx context.Context, exec bob.Executor, related ...*PublicreportQuickPhotoSetter) error { + if len(related) == 0 { + return nil + } + + var err error + + publicreportQuickPhotos1, err := insertPublicreportQuickQuickPhotos0(ctx, exec, related, publicreportQuick0) + if err != nil { + return err + } + + publicreportQuick0.R.QuickPhotos = append(publicreportQuick0.R.QuickPhotos, publicreportQuickPhotos1...) + + for _, rel := range publicreportQuickPhotos1 { + rel.R.Quick = publicreportQuick0 + } + return nil +} + +func (publicreportQuick0 *PublicreportQuick) AttachQuickPhotos(ctx context.Context, exec bob.Executor, related ...*PublicreportQuickPhoto) error { + if len(related) == 0 { + return nil + } + + var err error + publicreportQuickPhotos1 := PublicreportQuickPhotoSlice(related) + + _, err = attachPublicreportQuickQuickPhotos0(ctx, exec, len(related), publicreportQuickPhotos1, publicreportQuick0) + if err != nil { + return err + } + + publicreportQuick0.R.QuickPhotos = append(publicreportQuick0.R.QuickPhotos, publicreportQuickPhotos1...) + + for _, rel := range related { + rel.R.Quick = publicreportQuick0 + } + + return nil +} + +type publicreportQuickWhere[Q psql.Filterable] struct { + ID psql.WhereMod[Q, int32] + Created psql.WhereMod[Q, time.Time] + Comments psql.WhereMod[Q, string] + Location psql.WhereNullMod[Q, string] + H3cell psql.WhereNullMod[Q, string] + UUID psql.WhereMod[Q, uuid.UUID] +} + +func (publicreportQuickWhere[Q]) AliasedAs(alias string) publicreportQuickWhere[Q] { + return buildPublicreportQuickWhere[Q](buildPublicreportQuickColumns(alias)) +} + +func buildPublicreportQuickWhere[Q psql.Filterable](cols publicreportQuickColumns) publicreportQuickWhere[Q] { + return publicreportQuickWhere[Q]{ + ID: psql.Where[Q, int32](cols.ID), + Created: psql.Where[Q, time.Time](cols.Created), + Comments: psql.Where[Q, string](cols.Comments), + Location: psql.WhereNull[Q, string](cols.Location), + H3cell: psql.WhereNull[Q, string](cols.H3cell), + UUID: psql.Where[Q, uuid.UUID](cols.UUID), + } +} + +func (o *PublicreportQuick) Preload(name string, retrieved any) error { + if o == nil { + return nil + } + + switch name { + case "QuickPhotos": + rels, ok := retrieved.(PublicreportQuickPhotoSlice) + if !ok { + return fmt.Errorf("publicreportQuick cannot load %T as %q", retrieved, name) + } + + o.R.QuickPhotos = rels + + for _, rel := range rels { + if rel != nil { + rel.R.Quick = o + } + } + return nil + default: + return fmt.Errorf("publicreportQuick has no relationship %q", name) + } +} + +type publicreportQuickPreloader struct{} + +func buildPublicreportQuickPreloader() publicreportQuickPreloader { + return publicreportQuickPreloader{} +} + +type publicreportQuickThenLoader[Q orm.Loadable] struct { + QuickPhotos func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] +} + +func buildPublicreportQuickThenLoader[Q orm.Loadable]() publicreportQuickThenLoader[Q] { + type QuickPhotosLoadInterface interface { + LoadQuickPhotos(context.Context, bob.Executor, ...bob.Mod[*dialect.SelectQuery]) error + } + + return publicreportQuickThenLoader[Q]{ + QuickPhotos: thenLoadBuilder[Q]( + "QuickPhotos", + func(ctx context.Context, exec bob.Executor, retrieved QuickPhotosLoadInterface, mods ...bob.Mod[*dialect.SelectQuery]) error { + return retrieved.LoadQuickPhotos(ctx, exec, mods...) + }, + ), + } +} + +// LoadQuickPhotos loads the publicreportQuick's QuickPhotos into the .R struct +func (o *PublicreportQuick) LoadQuickPhotos(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error { + if o == nil { + return nil + } + + // Reset the relationship + o.R.QuickPhotos = nil + + related, err := o.QuickPhotos(mods...).All(ctx, exec) + if err != nil { + return err + } + + for _, rel := range related { + rel.R.Quick = o + } + + o.R.QuickPhotos = related + return nil +} + +// LoadQuickPhotos loads the publicreportQuick's QuickPhotos into the .R struct +func (os PublicreportQuickSlice) LoadQuickPhotos(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error { + if len(os) == 0 { + return nil + } + + publicreportQuickPhotos, err := os.QuickPhotos(mods...).All(ctx, exec) + if err != nil { + return err + } + + for _, o := range os { + if o == nil { + continue + } + + o.R.QuickPhotos = nil + } + + for _, o := range os { + if o == nil { + continue + } + + for _, rel := range publicreportQuickPhotos { + + if !(o.ID == rel.QuickID) { + continue + } + + rel.R.Quick = o + + o.R.QuickPhotos = append(o.R.QuickPhotos, rel) + } + } + + return nil +} + +type publicreportQuickJoins[Q dialect.Joinable] struct { + typ string + QuickPhotos modAs[Q, publicreportQuickPhotoColumns] +} + +func (j publicreportQuickJoins[Q]) aliasedAs(alias string) publicreportQuickJoins[Q] { + return buildPublicreportQuickJoins[Q](buildPublicreportQuickColumns(alias), j.typ) +} + +func buildPublicreportQuickJoins[Q dialect.Joinable](cols publicreportQuickColumns, typ string) publicreportQuickJoins[Q] { + return publicreportQuickJoins[Q]{ + typ: typ, + QuickPhotos: modAs[Q, publicreportQuickPhotoColumns]{ + c: PublicreportQuickPhotos.Columns, + f: func(to publicreportQuickPhotoColumns) bob.Mod[Q] { + mods := make(mods.QueryMods[Q], 0, 1) + + { + mods = append(mods, dialect.Join[Q](typ, PublicreportQuickPhotos.Name().As(to.Alias())).On( + to.QuickID.EQ(cols.ID), + )) + } + + return mods + }, + }, + } +} diff --git a/db/models/publicreport.quick_photo.bob.go b/db/models/publicreport.quick_photo.bob.go new file mode 100644 index 00000000..0dc99964 --- /dev/null +++ b/db/models/publicreport.quick_photo.bob.go @@ -0,0 +1,678 @@ +// Code generated by BobGen psql v0.0.4-0.20260105020634-53e08d840e47+dirty. DO NOT EDIT. +// This file is meant to be re-generated in place and/or deleted at any time. + +package models + +import ( + "context" + "fmt" + "io" + + "github.com/aarondl/opt/omit" + "github.com/google/uuid" + "github.com/stephenafamo/bob" + "github.com/stephenafamo/bob/dialect/psql" + "github.com/stephenafamo/bob/dialect/psql/dialect" + "github.com/stephenafamo/bob/dialect/psql/dm" + "github.com/stephenafamo/bob/dialect/psql/sm" + "github.com/stephenafamo/bob/dialect/psql/um" + "github.com/stephenafamo/bob/expr" + "github.com/stephenafamo/bob/mods" + "github.com/stephenafamo/bob/orm" + "github.com/stephenafamo/bob/types/pgtypes" +) + +// PublicreportQuickPhoto is an object representing the database table. +type PublicreportQuickPhoto struct { + ID int32 `db:"id,pk" ` + Size int64 `db:"size" ` + Filename string `db:"filename" ` + QuickID int32 `db:"quick_id" ` + UUID uuid.UUID `db:"uuid" ` + + R publicreportQuickPhotoR `db:"-" ` +} + +// PublicreportQuickPhotoSlice is an alias for a slice of pointers to PublicreportQuickPhoto. +// This should almost always be used instead of []*PublicreportQuickPhoto. +type PublicreportQuickPhotoSlice []*PublicreportQuickPhoto + +// PublicreportQuickPhotos contains methods to work with the quick_photo table +var PublicreportQuickPhotos = psql.NewTablex[*PublicreportQuickPhoto, PublicreportQuickPhotoSlice, *PublicreportQuickPhotoSetter]("publicreport", "quick_photo", buildPublicreportQuickPhotoColumns("publicreport.quick_photo")) + +// PublicreportQuickPhotosQuery is a query on the quick_photo table +type PublicreportQuickPhotosQuery = *psql.ViewQuery[*PublicreportQuickPhoto, PublicreportQuickPhotoSlice] + +// publicreportQuickPhotoR is where relationships are stored. +type publicreportQuickPhotoR struct { + Quick *PublicreportQuick // publicreport.quick_photo.quick_photo_quick_id_fkey +} + +func buildPublicreportQuickPhotoColumns(alias string) publicreportQuickPhotoColumns { + return publicreportQuickPhotoColumns{ + ColumnsExpr: expr.NewColumnsExpr( + "id", "size", "filename", "quick_id", "uuid", + ).WithParent("publicreport.quick_photo"), + tableAlias: alias, + ID: psql.Quote(alias, "id"), + Size: psql.Quote(alias, "size"), + Filename: psql.Quote(alias, "filename"), + QuickID: psql.Quote(alias, "quick_id"), + UUID: psql.Quote(alias, "uuid"), + } +} + +type publicreportQuickPhotoColumns struct { + expr.ColumnsExpr + tableAlias string + ID psql.Expression + Size psql.Expression + Filename psql.Expression + QuickID psql.Expression + UUID psql.Expression +} + +func (c publicreportQuickPhotoColumns) Alias() string { + return c.tableAlias +} + +func (publicreportQuickPhotoColumns) AliasedAs(alias string) publicreportQuickPhotoColumns { + return buildPublicreportQuickPhotoColumns(alias) +} + +// PublicreportQuickPhotoSetter is used for insert/upsert/update operations +// All values are optional, and do not have to be set +// Generated columns are not included +type PublicreportQuickPhotoSetter struct { + ID omit.Val[int32] `db:"id,pk" ` + Size omit.Val[int64] `db:"size" ` + Filename omit.Val[string] `db:"filename" ` + QuickID omit.Val[int32] `db:"quick_id" ` + UUID omit.Val[uuid.UUID] `db:"uuid" ` +} + +func (s PublicreportQuickPhotoSetter) SetColumns() []string { + vals := make([]string, 0, 5) + if s.ID.IsValue() { + vals = append(vals, "id") + } + if s.Size.IsValue() { + vals = append(vals, "size") + } + if s.Filename.IsValue() { + vals = append(vals, "filename") + } + if s.QuickID.IsValue() { + vals = append(vals, "quick_id") + } + if s.UUID.IsValue() { + vals = append(vals, "uuid") + } + return vals +} + +func (s PublicreportQuickPhotoSetter) Overwrite(t *PublicreportQuickPhoto) { + if s.ID.IsValue() { + t.ID = s.ID.MustGet() + } + if s.Size.IsValue() { + t.Size = s.Size.MustGet() + } + if s.Filename.IsValue() { + t.Filename = s.Filename.MustGet() + } + if s.QuickID.IsValue() { + t.QuickID = s.QuickID.MustGet() + } + if s.UUID.IsValue() { + t.UUID = s.UUID.MustGet() + } +} + +func (s *PublicreportQuickPhotoSetter) Apply(q *dialect.InsertQuery) { + q.AppendHooks(func(ctx context.Context, exec bob.Executor) (context.Context, error) { + return PublicreportQuickPhotos.BeforeInsertHooks.RunHooks(ctx, exec, s) + }) + + q.AppendValues(bob.ExpressionFunc(func(ctx context.Context, w io.StringWriter, d bob.Dialect, start int) ([]any, error) { + vals := make([]bob.Expression, 5) + if s.ID.IsValue() { + vals[0] = psql.Arg(s.ID.MustGet()) + } else { + vals[0] = psql.Raw("DEFAULT") + } + + if s.Size.IsValue() { + vals[1] = psql.Arg(s.Size.MustGet()) + } else { + vals[1] = psql.Raw("DEFAULT") + } + + if s.Filename.IsValue() { + vals[2] = psql.Arg(s.Filename.MustGet()) + } else { + vals[2] = psql.Raw("DEFAULT") + } + + if s.QuickID.IsValue() { + vals[3] = psql.Arg(s.QuickID.MustGet()) + } else { + vals[3] = psql.Raw("DEFAULT") + } + + if s.UUID.IsValue() { + vals[4] = psql.Arg(s.UUID.MustGet()) + } else { + vals[4] = psql.Raw("DEFAULT") + } + + return bob.ExpressSlice(ctx, w, d, start, vals, "", ", ", "") + })) +} + +func (s PublicreportQuickPhotoSetter) UpdateMod() bob.Mod[*dialect.UpdateQuery] { + return um.Set(s.Expressions()...) +} + +func (s PublicreportQuickPhotoSetter) Expressions(prefix ...string) []bob.Expression { + exprs := make([]bob.Expression, 0, 5) + + if s.ID.IsValue() { + exprs = append(exprs, expr.Join{Sep: " = ", Exprs: []bob.Expression{ + psql.Quote(append(prefix, "id")...), + psql.Arg(s.ID), + }}) + } + + if s.Size.IsValue() { + exprs = append(exprs, expr.Join{Sep: " = ", Exprs: []bob.Expression{ + psql.Quote(append(prefix, "size")...), + psql.Arg(s.Size), + }}) + } + + if s.Filename.IsValue() { + exprs = append(exprs, expr.Join{Sep: " = ", Exprs: []bob.Expression{ + psql.Quote(append(prefix, "filename")...), + psql.Arg(s.Filename), + }}) + } + + if s.QuickID.IsValue() { + exprs = append(exprs, expr.Join{Sep: " = ", Exprs: []bob.Expression{ + psql.Quote(append(prefix, "quick_id")...), + psql.Arg(s.QuickID), + }}) + } + + if s.UUID.IsValue() { + exprs = append(exprs, expr.Join{Sep: " = ", Exprs: []bob.Expression{ + psql.Quote(append(prefix, "uuid")...), + psql.Arg(s.UUID), + }}) + } + + return exprs +} + +// FindPublicreportQuickPhoto retrieves a single record by primary key +// If cols is empty Find will return all columns. +func FindPublicreportQuickPhoto(ctx context.Context, exec bob.Executor, IDPK int32, cols ...string) (*PublicreportQuickPhoto, error) { + if len(cols) == 0 { + return PublicreportQuickPhotos.Query( + sm.Where(PublicreportQuickPhotos.Columns.ID.EQ(psql.Arg(IDPK))), + ).One(ctx, exec) + } + + return PublicreportQuickPhotos.Query( + sm.Where(PublicreportQuickPhotos.Columns.ID.EQ(psql.Arg(IDPK))), + sm.Columns(PublicreportQuickPhotos.Columns.Only(cols...)), + ).One(ctx, exec) +} + +// PublicreportQuickPhotoExists checks the presence of a single record by primary key +func PublicreportQuickPhotoExists(ctx context.Context, exec bob.Executor, IDPK int32) (bool, error) { + return PublicreportQuickPhotos.Query( + sm.Where(PublicreportQuickPhotos.Columns.ID.EQ(psql.Arg(IDPK))), + ).Exists(ctx, exec) +} + +// AfterQueryHook is called after PublicreportQuickPhoto is retrieved from the database +func (o *PublicreportQuickPhoto) AfterQueryHook(ctx context.Context, exec bob.Executor, queryType bob.QueryType) error { + var err error + + switch queryType { + case bob.QueryTypeSelect: + ctx, err = PublicreportQuickPhotos.AfterSelectHooks.RunHooks(ctx, exec, PublicreportQuickPhotoSlice{o}) + case bob.QueryTypeInsert: + ctx, err = PublicreportQuickPhotos.AfterInsertHooks.RunHooks(ctx, exec, PublicreportQuickPhotoSlice{o}) + case bob.QueryTypeUpdate: + ctx, err = PublicreportQuickPhotos.AfterUpdateHooks.RunHooks(ctx, exec, PublicreportQuickPhotoSlice{o}) + case bob.QueryTypeDelete: + ctx, err = PublicreportQuickPhotos.AfterDeleteHooks.RunHooks(ctx, exec, PublicreportQuickPhotoSlice{o}) + } + + return err +} + +// primaryKeyVals returns the primary key values of the PublicreportQuickPhoto +func (o *PublicreportQuickPhoto) primaryKeyVals() bob.Expression { + return psql.Arg(o.ID) +} + +func (o *PublicreportQuickPhoto) pkEQ() dialect.Expression { + return psql.Quote("publicreport.quick_photo", "id").EQ(bob.ExpressionFunc(func(ctx context.Context, w io.StringWriter, d bob.Dialect, start int) ([]any, error) { + return o.primaryKeyVals().WriteSQL(ctx, w, d, start) + })) +} + +// Update uses an executor to update the PublicreportQuickPhoto +func (o *PublicreportQuickPhoto) Update(ctx context.Context, exec bob.Executor, s *PublicreportQuickPhotoSetter) error { + v, err := PublicreportQuickPhotos.Update(s.UpdateMod(), um.Where(o.pkEQ())).One(ctx, exec) + if err != nil { + return err + } + + o.R = v.R + *o = *v + + return nil +} + +// Delete deletes a single PublicreportQuickPhoto record with an executor +func (o *PublicreportQuickPhoto) Delete(ctx context.Context, exec bob.Executor) error { + _, err := PublicreportQuickPhotos.Delete(dm.Where(o.pkEQ())).Exec(ctx, exec) + return err +} + +// Reload refreshes the PublicreportQuickPhoto using the executor +func (o *PublicreportQuickPhoto) Reload(ctx context.Context, exec bob.Executor) error { + o2, err := PublicreportQuickPhotos.Query( + sm.Where(PublicreportQuickPhotos.Columns.ID.EQ(psql.Arg(o.ID))), + ).One(ctx, exec) + if err != nil { + return err + } + o2.R = o.R + *o = *o2 + + return nil +} + +// AfterQueryHook is called after PublicreportQuickPhotoSlice is retrieved from the database +func (o PublicreportQuickPhotoSlice) AfterQueryHook(ctx context.Context, exec bob.Executor, queryType bob.QueryType) error { + var err error + + switch queryType { + case bob.QueryTypeSelect: + ctx, err = PublicreportQuickPhotos.AfterSelectHooks.RunHooks(ctx, exec, o) + case bob.QueryTypeInsert: + ctx, err = PublicreportQuickPhotos.AfterInsertHooks.RunHooks(ctx, exec, o) + case bob.QueryTypeUpdate: + ctx, err = PublicreportQuickPhotos.AfterUpdateHooks.RunHooks(ctx, exec, o) + case bob.QueryTypeDelete: + ctx, err = PublicreportQuickPhotos.AfterDeleteHooks.RunHooks(ctx, exec, o) + } + + return err +} + +func (o PublicreportQuickPhotoSlice) pkIN() dialect.Expression { + if len(o) == 0 { + return psql.Raw("NULL") + } + + return psql.Quote("publicreport.quick_photo", "id").In(bob.ExpressionFunc(func(ctx context.Context, w io.StringWriter, d bob.Dialect, start int) ([]any, error) { + pkPairs := make([]bob.Expression, len(o)) + for i, row := range o { + pkPairs[i] = row.primaryKeyVals() + } + return bob.ExpressSlice(ctx, w, d, start, pkPairs, "", ", ", "") + })) +} + +// copyMatchingRows finds models in the given slice that have the same primary key +// then it first copies the existing relationships from the old model to the new model +// and then replaces the old model in the slice with the new model +func (o PublicreportQuickPhotoSlice) copyMatchingRows(from ...*PublicreportQuickPhoto) { + for i, old := range o { + for _, new := range from { + if new.ID != old.ID { + continue + } + new.R = old.R + o[i] = new + break + } + } +} + +// UpdateMod modifies an update query with "WHERE primary_key IN (o...)" +func (o PublicreportQuickPhotoSlice) UpdateMod() bob.Mod[*dialect.UpdateQuery] { + return bob.ModFunc[*dialect.UpdateQuery](func(q *dialect.UpdateQuery) { + q.AppendHooks(func(ctx context.Context, exec bob.Executor) (context.Context, error) { + return PublicreportQuickPhotos.BeforeUpdateHooks.RunHooks(ctx, exec, o) + }) + + q.AppendLoader(bob.LoaderFunc(func(ctx context.Context, exec bob.Executor, retrieved any) error { + var err error + switch retrieved := retrieved.(type) { + case *PublicreportQuickPhoto: + o.copyMatchingRows(retrieved) + case []*PublicreportQuickPhoto: + o.copyMatchingRows(retrieved...) + case PublicreportQuickPhotoSlice: + o.copyMatchingRows(retrieved...) + default: + // If the retrieved value is not a PublicreportQuickPhoto or a slice of PublicreportQuickPhoto + // then run the AfterUpdateHooks on the slice + _, err = PublicreportQuickPhotos.AfterUpdateHooks.RunHooks(ctx, exec, o) + } + + return err + })) + + q.AppendWhere(o.pkIN()) + }) +} + +// DeleteMod modifies an delete query with "WHERE primary_key IN (o...)" +func (o PublicreportQuickPhotoSlice) DeleteMod() bob.Mod[*dialect.DeleteQuery] { + return bob.ModFunc[*dialect.DeleteQuery](func(q *dialect.DeleteQuery) { + q.AppendHooks(func(ctx context.Context, exec bob.Executor) (context.Context, error) { + return PublicreportQuickPhotos.BeforeDeleteHooks.RunHooks(ctx, exec, o) + }) + + q.AppendLoader(bob.LoaderFunc(func(ctx context.Context, exec bob.Executor, retrieved any) error { + var err error + switch retrieved := retrieved.(type) { + case *PublicreportQuickPhoto: + o.copyMatchingRows(retrieved) + case []*PublicreportQuickPhoto: + o.copyMatchingRows(retrieved...) + case PublicreportQuickPhotoSlice: + o.copyMatchingRows(retrieved...) + default: + // If the retrieved value is not a PublicreportQuickPhoto or a slice of PublicreportQuickPhoto + // then run the AfterDeleteHooks on the slice + _, err = PublicreportQuickPhotos.AfterDeleteHooks.RunHooks(ctx, exec, o) + } + + return err + })) + + q.AppendWhere(o.pkIN()) + }) +} + +func (o PublicreportQuickPhotoSlice) UpdateAll(ctx context.Context, exec bob.Executor, vals PublicreportQuickPhotoSetter) error { + if len(o) == 0 { + return nil + } + + _, err := PublicreportQuickPhotos.Update(vals.UpdateMod(), o.UpdateMod()).All(ctx, exec) + return err +} + +func (o PublicreportQuickPhotoSlice) DeleteAll(ctx context.Context, exec bob.Executor) error { + if len(o) == 0 { + return nil + } + + _, err := PublicreportQuickPhotos.Delete(o.DeleteMod()).Exec(ctx, exec) + return err +} + +func (o PublicreportQuickPhotoSlice) ReloadAll(ctx context.Context, exec bob.Executor) error { + if len(o) == 0 { + return nil + } + + o2, err := PublicreportQuickPhotos.Query(sm.Where(o.pkIN())).All(ctx, exec) + if err != nil { + return err + } + + o.copyMatchingRows(o2...) + + return nil +} + +// Quick starts a query for related objects on publicreport.quick +func (o *PublicreportQuickPhoto) Quick(mods ...bob.Mod[*dialect.SelectQuery]) PublicreportQuicksQuery { + return PublicreportQuicks.Query(append(mods, + sm.Where(PublicreportQuicks.Columns.ID.EQ(psql.Arg(o.QuickID))), + )...) +} + +func (os PublicreportQuickPhotoSlice) Quick(mods ...bob.Mod[*dialect.SelectQuery]) PublicreportQuicksQuery { + pkQuickID := make(pgtypes.Array[int32], 0, len(os)) + for _, o := range os { + if o == nil { + continue + } + pkQuickID = append(pkQuickID, o.QuickID) + } + PKArgExpr := psql.Select(sm.Columns( + psql.F("unnest", psql.Cast(psql.Arg(pkQuickID), "integer[]")), + )) + + return PublicreportQuicks.Query(append(mods, + sm.Where(psql.Group(PublicreportQuicks.Columns.ID).OP("IN", PKArgExpr)), + )...) +} + +func attachPublicreportQuickPhotoQuick0(ctx context.Context, exec bob.Executor, count int, publicreportQuickPhoto0 *PublicreportQuickPhoto, publicreportQuick1 *PublicreportQuick) (*PublicreportQuickPhoto, error) { + setter := &PublicreportQuickPhotoSetter{ + QuickID: omit.From(publicreportQuick1.ID), + } + + err := publicreportQuickPhoto0.Update(ctx, exec, setter) + if err != nil { + return nil, fmt.Errorf("attachPublicreportQuickPhotoQuick0: %w", err) + } + + return publicreportQuickPhoto0, nil +} + +func (publicreportQuickPhoto0 *PublicreportQuickPhoto) InsertQuick(ctx context.Context, exec bob.Executor, related *PublicreportQuickSetter) error { + var err error + + publicreportQuick1, err := PublicreportQuicks.Insert(related).One(ctx, exec) + if err != nil { + return fmt.Errorf("inserting related objects: %w", err) + } + + _, err = attachPublicreportQuickPhotoQuick0(ctx, exec, 1, publicreportQuickPhoto0, publicreportQuick1) + if err != nil { + return err + } + + publicreportQuickPhoto0.R.Quick = publicreportQuick1 + + publicreportQuick1.R.QuickPhotos = append(publicreportQuick1.R.QuickPhotos, publicreportQuickPhoto0) + + return nil +} + +func (publicreportQuickPhoto0 *PublicreportQuickPhoto) AttachQuick(ctx context.Context, exec bob.Executor, publicreportQuick1 *PublicreportQuick) error { + var err error + + _, err = attachPublicreportQuickPhotoQuick0(ctx, exec, 1, publicreportQuickPhoto0, publicreportQuick1) + if err != nil { + return err + } + + publicreportQuickPhoto0.R.Quick = publicreportQuick1 + + publicreportQuick1.R.QuickPhotos = append(publicreportQuick1.R.QuickPhotos, publicreportQuickPhoto0) + + return nil +} + +type publicreportQuickPhotoWhere[Q psql.Filterable] struct { + ID psql.WhereMod[Q, int32] + Size psql.WhereMod[Q, int64] + Filename psql.WhereMod[Q, string] + QuickID psql.WhereMod[Q, int32] + UUID psql.WhereMod[Q, uuid.UUID] +} + +func (publicreportQuickPhotoWhere[Q]) AliasedAs(alias string) publicreportQuickPhotoWhere[Q] { + return buildPublicreportQuickPhotoWhere[Q](buildPublicreportQuickPhotoColumns(alias)) +} + +func buildPublicreportQuickPhotoWhere[Q psql.Filterable](cols publicreportQuickPhotoColumns) publicreportQuickPhotoWhere[Q] { + return publicreportQuickPhotoWhere[Q]{ + ID: psql.Where[Q, int32](cols.ID), + Size: psql.Where[Q, int64](cols.Size), + Filename: psql.Where[Q, string](cols.Filename), + QuickID: psql.Where[Q, int32](cols.QuickID), + UUID: psql.Where[Q, uuid.UUID](cols.UUID), + } +} + +func (o *PublicreportQuickPhoto) Preload(name string, retrieved any) error { + if o == nil { + return nil + } + + switch name { + case "Quick": + rel, ok := retrieved.(*PublicreportQuick) + if !ok { + return fmt.Errorf("publicreportQuickPhoto cannot load %T as %q", retrieved, name) + } + + o.R.Quick = rel + + if rel != nil { + rel.R.QuickPhotos = PublicreportQuickPhotoSlice{o} + } + return nil + default: + return fmt.Errorf("publicreportQuickPhoto has no relationship %q", name) + } +} + +type publicreportQuickPhotoPreloader struct { + Quick func(...psql.PreloadOption) psql.Preloader +} + +func buildPublicreportQuickPhotoPreloader() publicreportQuickPhotoPreloader { + return publicreportQuickPhotoPreloader{ + Quick: func(opts ...psql.PreloadOption) psql.Preloader { + return psql.Preload[*PublicreportQuick, PublicreportQuickSlice](psql.PreloadRel{ + Name: "Quick", + Sides: []psql.PreloadSide{ + { + From: PublicreportQuickPhotos, + To: PublicreportQuicks, + FromColumns: []string{"quick_id"}, + ToColumns: []string{"id"}, + }, + }, + }, PublicreportQuicks.Columns.Names(), opts...) + }, + } +} + +type publicreportQuickPhotoThenLoader[Q orm.Loadable] struct { + Quick func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] +} + +func buildPublicreportQuickPhotoThenLoader[Q orm.Loadable]() publicreportQuickPhotoThenLoader[Q] { + type QuickLoadInterface interface { + LoadQuick(context.Context, bob.Executor, ...bob.Mod[*dialect.SelectQuery]) error + } + + return publicreportQuickPhotoThenLoader[Q]{ + Quick: thenLoadBuilder[Q]( + "Quick", + func(ctx context.Context, exec bob.Executor, retrieved QuickLoadInterface, mods ...bob.Mod[*dialect.SelectQuery]) error { + return retrieved.LoadQuick(ctx, exec, mods...) + }, + ), + } +} + +// LoadQuick loads the publicreportQuickPhoto's Quick into the .R struct +func (o *PublicreportQuickPhoto) LoadQuick(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error { + if o == nil { + return nil + } + + // Reset the relationship + o.R.Quick = nil + + related, err := o.Quick(mods...).One(ctx, exec) + if err != nil { + return err + } + + related.R.QuickPhotos = PublicreportQuickPhotoSlice{o} + + o.R.Quick = related + return nil +} + +// LoadQuick loads the publicreportQuickPhoto's Quick into the .R struct +func (os PublicreportQuickPhotoSlice) LoadQuick(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error { + if len(os) == 0 { + return nil + } + + publicreportQuicks, err := os.Quick(mods...).All(ctx, exec) + if err != nil { + return err + } + + for _, o := range os { + if o == nil { + continue + } + + for _, rel := range publicreportQuicks { + + if !(o.QuickID == rel.ID) { + continue + } + + rel.R.QuickPhotos = append(rel.R.QuickPhotos, o) + + o.R.Quick = rel + break + } + } + + return nil +} + +type publicreportQuickPhotoJoins[Q dialect.Joinable] struct { + typ string + Quick modAs[Q, publicreportQuickColumns] +} + +func (j publicreportQuickPhotoJoins[Q]) aliasedAs(alias string) publicreportQuickPhotoJoins[Q] { + return buildPublicreportQuickPhotoJoins[Q](buildPublicreportQuickPhotoColumns(alias), j.typ) +} + +func buildPublicreportQuickPhotoJoins[Q dialect.Joinable](cols publicreportQuickPhotoColumns, typ string) publicreportQuickPhotoJoins[Q] { + return publicreportQuickPhotoJoins[Q]{ + typ: typ, + Quick: modAs[Q, publicreportQuickColumns]{ + c: PublicreportQuicks.Columns, + f: func(to publicreportQuickColumns) bob.Mod[Q] { + mods := make(mods.QueryMods[Q], 0, 1) + + { + mods = append(mods, dialect.Join[Q](typ, PublicreportQuicks.Name().As(to.Alias())).On( + to.ID.EQ(cols.QuickID), + )) + } + + return mods + }, + }, + } +} diff --git a/db/sql/trapcount_by_location_id.bob_test.go b/db/sql/trapcount_by_location_id.bob_test.go index d12cbfc7..6737508b 100644 --- a/db/sql/trapcount_by_location_id.bob_test.go +++ b/db/sql/trapcount_by_location_id.bob_test.go @@ -10,7 +10,6 @@ import ( "testing" "github.com/google/go-cmp/cmp" - "github.com/google/uuid" "github.com/stephenafamo/bob" "github.com/stephenafamo/bob/dialect/psql" testutils "github.com/stephenafamo/bob/test/utils" diff --git a/db/sql/trapdata_by_location_id_recent.bob_test.go b/db/sql/trapdata_by_location_id_recent.bob_test.go index e37d969a..cb6a7042 100644 --- a/db/sql/trapdata_by_location_id_recent.bob_test.go +++ b/db/sql/trapdata_by_location_id_recent.bob_test.go @@ -10,7 +10,6 @@ import ( "testing" "github.com/google/go-cmp/cmp" - "github.com/google/uuid" "github.com/stephenafamo/bob" "github.com/stephenafamo/bob/dialect/psql" testutils "github.com/stephenafamo/bob/test/utils" diff --git a/h3utils/h3.go b/h3utils/h3.go index deea635f..c178de09 100644 --- a/h3utils/h3.go +++ b/h3utils/h3.go @@ -77,7 +77,7 @@ func scaleCell(cell h3.Cell, resolution int) (h3.Cell, error) { return scaled, nil } -func getCell(x, y float64, resolution int) (h3.Cell, error) { +func GetCell(x, y float64, resolution int) (h3.Cell, error) { latLng := h3.NewLatLng(y, x) return h3.LatLngToCell(latLng, resolution) } diff --git a/htmlpage/html.go b/htmlpage/html.go index 5cd9db18..a34d8197 100644 --- a/htmlpage/html.go +++ b/htmlpage/html.go @@ -42,7 +42,7 @@ func (bt *BuiltTemplate) executeTemplate(w io.Writer, data any) error { w.Write([]byte("Failed to read from disk: ")) return errors.New("Template parsing failed") } - log.Debug().Str("name", templ.Name()).Msg("Parsed template") + //log.Debug().Str("name", templ.Name()).Msg("Parsed template") return templ.ExecuteTemplate(w, name, data) } else { name := path.Base(bt.files[0]) @@ -137,7 +137,7 @@ func parseEmbedded(embeddedFiles embed.FS, subdir string, files []string) *templ func parseFromDisk(files []string) (*template.Template, error) { funcMap := makeFuncMap() name := path.Base(files[0]) - log.Debug().Str("name", name).Strs("files", files).Msg("parsing from disk") + //log.Debug().Str("name", name).Strs("files", files).Msg("parsing from disk") templ, err := template.New(name).Funcs(funcMap).ParseFiles(files...) if err != nil { return nil, fmt.Errorf("Failed to parse %s: %w", files, err) diff --git a/htmlpage/public-reports/template/quick.html b/htmlpage/public-reports/template/quick.html index ffb86d61..a6c910e1 100644 --- a/htmlpage/public-reports/template/quick.html +++ b/htmlpage/public-reports/template/quick.html @@ -212,13 +212,13 @@ document.addEventListener('DOMContentLoaded', function() { // Navigate to the URL the server specified window.location.href = response.url; return; - } else { - console.error("Not ok response:", response); } + console.error("not ok server response", response); + throw new Error("Server error " + response.status); }) .catch(error => { console.error('Error:', error); - alert('There was a problem submitting your report. Please try again.'); + alert('There was a problem submitting your report. Please try again. If this happens a few times, please let us know.'); // Re-enable submit button submitButton.disabled = false; diff --git a/public-report/endpoint.go b/public-report/endpoint.go index 2d278605..6e7d0aa2 100644 --- a/public-report/endpoint.go +++ b/public-report/endpoint.go @@ -2,13 +2,27 @@ package publicreport import ( "bytes" + "fmt" "io" "net/http" + "strconv" + "time" + "github.com/Gleipnir-Technology/nidus-sync/db" + "github.com/Gleipnir-Technology/nidus-sync/db/models" + "github.com/Gleipnir-Technology/nidus-sync/h3utils" "github.com/Gleipnir-Technology/nidus-sync/htmlpage" "github.com/Gleipnir-Technology/nidus-sync/htmlpage/public-reports" + "github.com/Gleipnir-Technology/nidus-sync/userfile" + "github.com/aarondl/opt/omit" + "github.com/aarondl/opt/omitnull" "github.com/go-chi/chi/v5" + "github.com/google/uuid" "github.com/rs/zerolog/log" + "github.com/stephenafamo/bob/dialect/psql" + //"github.com/stephenafamo/bob/dialect/psql/dialect" + //"github.com/stephenafamo/bob/dialect/psql/im" + "github.com/stephenafamo/bob/dialect/psql/um" ) func Router() chi.Router { @@ -78,12 +92,51 @@ func postQuick(w http.ResponseWriter, r *http.Request) { respondError(w, "Failed to parse form", err, http.StatusBadRequest) return } - latitude := r.FormValue("latitude") - longitude := r.FormValue("longitude") + lat := r.FormValue("latitude") + lng := r.FormValue("longitude") created := r.FormValue("created") + comments := r.FormValue("comments") //photos := r.FormValue("photos") - log.Info().Str("latitude", latitude).Str("longitude", longitude).Str("created", created).Msg("Got upload") + latitude, err := strconv.ParseFloat(lat, 64) + if err != nil { + respondError(w, "Failed to create parse latitude", err, http.StatusBadRequest) + return + } + longitude, err := strconv.ParseFloat(lng, 64) + if err != nil { + respondError(w, "Failed to create parse longitude", err, http.StatusBadRequest) + return + } + u, err := uuid.NewUUID() + if err != nil { + respondError(w, "Failed to create quick report uuid", err, http.StatusInternalServerError) + return + } + c, err := h3utils.GetCell(longitude, latitude, 15) + setter := models.PublicreportQuickSetter{ + Created: omit.From(time.Now()), + Comments: omit.From(comments), + //Location: omitnull.From(fmt.Sprintf("ST_GeometryFromText(Point(%s %s))", longitude, latitude)), + H3cell: omitnull.From(c.String()), + UUID: omit.From(u), + } + quick, err := models.PublicreportQuicks.Insert(&setter).One(r.Context(), db.PGInstance.BobDB) + if err != nil { + respondError(w, "Failed to create database record", err, http.StatusInternalServerError) + return + } + _, err = psql.Update( + um.Table("publicreport.quick"), + um.SetCol("location").To(fmt.Sprintf("ST_GeometryFromText('Point(%f %f)')", longitude, latitude)), + um.Where(psql.Quote("id").EQ(psql.Arg(quick.ID))), + ).Exec(r.Context(), db.PGInstance.BobDB) + if err != nil { + respondError(w, "Failed to insert publicreport", err, http.StatusInternalServerError) + return + } + log.Info().Float64("latitude", latitude).Float64("longitude", longitude).Str("created", created).Msg("Got upload") + photoSetters := make([]*models.PublicreportQuickPhotoSetter, 0) for _, fheaders := range r.MultipartForm.File { for _, headers := range fheaders { file, err := headers.Open() @@ -113,8 +166,24 @@ func postQuick(w http.ResponseWriter, r *http.Request) { return } log.Info().Int64("size", fileSize).Str("filename", headers.Filename).Str("content-type", contentType).Msg("Got an uploaded file") + u, err := uuid.NewUUID() + if err != nil { + respondError(w, "Failed to create quick report photo uuid", err, http.StatusInternalServerError) + continue + } + err = userfile.PublicImageFileContentWrite(u, file) + photoSetters = append(photoSetters, &models.PublicreportQuickPhotoSetter{ + Size: omit.From(fileSize), + Filename: omit.From(headers.Filename), + UUID: omit.From(u), + }) } } + /*err = quick.InsertQuickPhotos(r.Context(), db.PGInstance.BobDB, photoSetters...) + if err != nil { + respondError(w, "Failed to create photo records", err, http.StatusInternalServerError) + return + }*/ http.Redirect(w, r, "/quick-submit-complete?report=123", http.StatusFound) } diff --git a/queue/label_studio.go b/queue/label_studio.go index ca665f62..1cf1a1d2 100644 --- a/queue/label_studio.go +++ b/queue/label_studio.go @@ -130,7 +130,7 @@ func processLabelTask(ctx context.Context, minioClient *minio.Client, minioBucke func createTask(client *labelstudio.Client, project *labelstudio.Project, minioClient *minio.Client, bucket string, customer string, note *models.NoteAudio) error { audioRef := fmt.Sprintf("s3://%s/%s-normalized.m4a", bucket, note.UUID) - audioFile := fmt.Sprintf("%s/%s-normalized.m4a", config.UserFilesDirectory, note.UUID) + audioFile := fmt.Sprintf("%s/%s-normalized.m4a", config.FilesDirectoryUser, note.UUID) uploadPath := fmt.Sprintf("%s-normalized.m4a", note.UUID) if !minioClient.ObjectExists(bucket, uploadPath) { diff --git a/userfile/userfile.go b/userfile/userfile.go index 38ff4464..2608d975 100644 --- a/userfile/userfile.go +++ b/userfile/userfile.go @@ -11,16 +11,16 @@ import ( ) func AudioFileContentPathRaw(audioUUID string) string { - return fmt.Sprintf("%s/%s.m4a", config.UserFilesDirectory, audioUUID) + return fmt.Sprintf("%s/%s.m4a", config.FilesDirectoryUser, audioUUID) } func AudioFileContentPathMp3(audioUUID string) string { - return fmt.Sprintf("%s/%s.mp3", config.UserFilesDirectory, audioUUID) + return fmt.Sprintf("%s/%s.mp3", config.FilesDirectoryUser, audioUUID) } func AudioFileContentPathNormalized(audioUUID string) string { - return fmt.Sprintf("%s/%s-normalized.m4a", config.UserFilesDirectory, audioUUID) + return fmt.Sprintf("%s/%s-normalized.m4a", config.FilesDirectoryUser, audioUUID) } func AudioFileContentPathOgg(audioUUID string) string { - return fmt.Sprintf("%s/%s.ogg", config.UserFilesDirectory, audioUUID) + return fmt.Sprintf("%s/%s.ogg", config.FilesDirectoryUser, audioUUID) } func AudioFileContentWrite(audioUUID uuid.UUID, body io.Reader) error { // Create file in configured directory @@ -41,7 +41,7 @@ func AudioFileContentWrite(audioUUID uuid.UUID, body io.Reader) error { return nil } func ImageFileContentPathRaw(uid string) string { - return fmt.Sprintf("%s/%s.raw", config.UserFilesDirectory, uid) + return fmt.Sprintf("%s/%s.raw", config.FilesDirectoryUser, uid) } func ImageFileContentWrite(uid uuid.UUID, body io.Reader) error { filepath := ImageFileContentPathRaw(uid.String()) @@ -60,3 +60,24 @@ func ImageFileContentWrite(uid uuid.UUID, body io.Reader) error { } return nil } +func PublicImageFileContentWrite(uid uuid.UUID, body io.Reader) error { + // Create file in configured directory + filepath := PublicImageFileContentPathRaw(uid.String()) + dst, err := os.Create(filepath) + if err != nil { + log.Printf("Failed to create public image file at %s: %v\n", filepath, err) + return fmt.Errorf("Failed to create public image file at %s: %v", filepath, err) + } + defer dst.Close() + + // Copy rest of request body to file + _, err = io.Copy(dst, body) + if err != nil { + return fmt.Errorf("Unable to save file to create audio file at %s: %v", filepath, err) + } + log.Printf("Saved audio content to %s\n", filepath) + return nil +} +func PublicImageFileContentPathRaw(uid string) string { + return fmt.Sprintf("%s/%s.raw", config.FilesDirectoryPublic, uid) +}