From fcd95f1a2518b6d3313452c742f28225c1873e2a Mon Sep 17 00:00:00 2001 From: Eli Ribble Date: Thu, 7 May 2026 10:39:17 +0000 Subject: [PATCH] Get back to compiling, but using new jet for publicreport This was an epically long change, and a terrible idea, but it compiles. This was essentially a cascade that came about because I can't blend jet and bob in the same transaction. In for a penny, I guess... --- api/configuration.go | 8 +- cmd/test-jet/main.go | 53 + db/connection.go | 105 +- db/dberrors/communication_log_entry.bob.go | 17 + db/dbinfo/communication.bob.go | 214 +-- db/dbinfo/communication_log_entry.bob.go | 157 ++ db/dbinfo/publicreport.compliance.bob.go | 2 +- db/enums/enums.bob.go | 330 +++- db/jet/main.go | 58 +- db/migrations/00147_communication.sql | 38 +- .../00148_communications_from_reports.sql | 35 +- db/migrations/00149_permissionaccesstype.sql | 6 +- .../00150_communication_possible_status.sql | 6 - db/models/bob_loaders.bob.go | 4 + db/models/bob_where.bob.go | 3 + db/models/communication.bob.go | 1632 +++-------------- db/models/communication_log_entry.bob.go | 815 ++++++++ db/models/publicreport.compliance.bob.go | 44 +- db/models/user_.bob.go | 1119 ++--------- db/query/arcgis/account.go | 4 +- db/query/arcgis/oauth.go | 18 +- db/query/arcgis/service_feature.go | 6 +- db/query/arcgis/service_map.go | 4 +- db/query/arcgis/user.go | 4 +- db/query/public/address.go | 69 + db/query/public/communication.go | 46 +- db/query/public/communication_log_entry.go | 19 + db/query/public/signal.go | 19 + db/query/public/site.go | 38 + db/query/publicreport/compliance.go | 34 + db/query/publicreport/image.go | 16 + db/query/publicreport/image_exif.go | 20 + db/query/publicreport/nuisance.go | 17 + db/query/publicreport/report.go | 57 +- db/query/publicreport/report_image.go | 21 + db/query/publicreport/report_log.go | 16 + db/query/publicreport/water.go | 17 + db/tx.go | 83 + db/types/box2d.go | 8 - db/updater.go | 64 + geomutil/geomutil.go | 9 + go.mod | 9 +- go.sum | 18 +- platform/address.go | 9 +- platform/address/address.go | 100 + platform/arcgis.go | 37 +- platform/client.go | 2 +- platform/communication.go | 37 +- platform/district.go | 4 +- platform/geocode/address.go | 180 +- platform/geocode/by_gid.go | 4 +- platform/geocode/geocode.go | 9 +- platform/image.go | 72 +- platform/oauth.go | 4 +- platform/oauth/oauth.go | 6 +- platform/publicreport.go | 309 ++-- platform/publicreport/address.go | 15 +- platform/signal.go | 110 +- platform/site.go | 23 +- platform/types/address.go | 12 +- platform/types/location.go | 5 + resource/communication.go | 61 +- resource/publicreport_compliance.go | 165 +- resource/publicreport_nuisance.go | 77 +- resource/publicreport_water.go | 83 +- 65 files changed, 3129 insertions(+), 3457 deletions(-) create mode 100644 cmd/test-jet/main.go create mode 100644 db/dberrors/communication_log_entry.bob.go create mode 100644 db/dbinfo/communication_log_entry.bob.go delete mode 100644 db/migrations/00150_communication_possible_status.sql create mode 100644 db/models/communication_log_entry.bob.go create mode 100644 db/query/public/address.go create mode 100644 db/query/public/communication_log_entry.go create mode 100644 db/query/public/signal.go create mode 100644 db/query/public/site.go create mode 100644 db/query/publicreport/compliance.go create mode 100644 db/query/publicreport/image.go create mode 100644 db/query/publicreport/image_exif.go create mode 100644 db/query/publicreport/nuisance.go create mode 100644 db/query/publicreport/report_image.go create mode 100644 db/query/publicreport/report_log.go create mode 100644 db/query/publicreport/water.go create mode 100644 db/tx.go delete mode 100644 db/types/box2d.go create mode 100644 db/updater.go create mode 100644 geomutil/geomutil.go create mode 100644 platform/address/address.go diff --git a/api/configuration.go b/api/configuration.go index 49e6c4d5..1e77e9ff 100644 --- a/api/configuration.go +++ b/api/configuration.go @@ -28,7 +28,7 @@ type contentSettingOrganization struct { type contentSettingIntegration struct { ArcGISAccount *model.Account ArcGISOAuth *model.OAuthToken - ServiceMaps []*model.ServiceMap + ServiceMaps []model.ServiceMap } func getConfigurationOrganization(ctx context.Context, r *http.Request, u platform.User) (*html.Response[contentSettingOrganization], *nhttp.ErrorWithStatus) { @@ -83,8 +83,8 @@ func getConfigurationIntegrationArcgis(ctx context.Context, r *http.Request, u p if err != nil { return nil, nhttp.NewError("Failed to get oauth: %w", err) } - var account *model.Account - var service_maps []*model.ServiceMap + var account model.Account + var service_maps []model.ServiceMap account_id := u.Organization.ArcgisAccountID() if account_id != "" { account, err = queryarcgis.AccountFromID(ctx, account_id) @@ -97,7 +97,7 @@ func getConfigurationIntegrationArcgis(ctx context.Context, r *http.Request, u p } } data := contentSettingIntegration{ - ArcGISAccount: account, + ArcGISAccount: &account, ArcGISOAuth: oauth, ServiceMaps: service_maps, } diff --git a/cmd/test-jet/main.go b/cmd/test-jet/main.go new file mode 100644 index 00000000..1fc6bcbc --- /dev/null +++ b/cmd/test-jet/main.go @@ -0,0 +1,53 @@ +package main + +import ( + "context" + "log" + "os" + + "github.com/Gleipnir-Technology/nidus-sync/config" + "github.com/Gleipnir-Technology/nidus-sync/db" + "github.com/Gleipnir-Technology/nidus-sync/db/query/public" +) + +func main() { + err := config.Parse() + if err != nil { + log.Printf("failed on config: %v", err) + os.Exit(1) + } + ctx := context.TODO() + err = db.InitializeDatabase(ctx, config.PGDSN) + if err != nil { + log.Printf("failed on db: %v", err) + os.Exit(2) + } + + txn, err := db.BeginTxn(ctx) + if err != nil { + log.Printf("failed on txn: %v", err) + os.Exit(3) + } + defer txn.Rollback(ctx) + log.Printf("doing address") + gid := "openaddresses:address:us/ca/tulare-addresses-county:0dc28458fd03e3fa" + address, err := public.AddressFromGID(ctx, txn, gid) + if err != nil { + log.Printf("failed on query: %v", err) + os.Exit(4) + } + //log.Printf("address %d lat %f lng %f", address.ID, *address.LocationLatitude, *address.LocationLongitude) + log.Printf("Address id %d location %s, lat %f, lng %f", address.ID, address.Location, *address.LocationLatitude, *address.LocationLongitude) + txn.Commit(ctx) + + /* + log.Printf("doing comm") + id := int64(1) + comm, err := public.CommunicationFromID(ctx, id) + if err != nil { + log.Printf("failed on query: %v", err) + os.Exit(4) + } + log.Printf("communication %d", comm.ID) + */ +} diff --git a/db/connection.go b/db/connection.go index dd35cc53..b7344413 100644 --- a/db/connection.go +++ b/db/connection.go @@ -7,7 +7,6 @@ import ( "errors" "fmt" "io/fs" - "sync" //"github.com/georgysavva/scany/v2/pgxscan" //"github.com/jackc/pgx/v5" @@ -19,8 +18,11 @@ import ( "github.com/pressly/goose/v3" "github.com/rs/zerolog/log" "github.com/stephenafamo/scan" + pgxgeom "github.com/twpayne/pgx-geom" ) +var ErrNoRows = pgx.ErrNoRows + //go:embed migrations/*.sql var embedMigrations embed.FS @@ -31,21 +33,15 @@ type pginstance struct { var ( PGInstance *pginstance - pgOnce sync.Once ) -type Tx = pgx.Tx - -func BeginTxn(ctx context.Context) (pgx.Tx, error) { - return PGInstance.PGXPool.BeginTx(ctx, pgx.TxOptions{}) -} func ExecuteNone(ctx context.Context, stmt postgres.Statement) error { query, args := stmt.Sql() _, err := PGInstance.PGXPool.Query(ctx, query, args...) return err } -func ExecuteNoneTx(ctx context.Context, txn Tx, stmt postgres.Statement) error { +func ExecuteNoneTx(ctx context.Context, txn Ex, stmt postgres.Statement) error { query, args := stmt.Sql() _, err := txn.Query(ctx, query, args...) @@ -57,46 +53,81 @@ func ExecuteNoneTxBob(ctx context.Context, txn bob.Tx, stmt postgres.Statement) _, err := txn.QueryContext(ctx, query, args...) return err } -func ExecuteOne[T any](ctx context.Context, stmt postgres.Statement) (*T, error) { +func ExecuteOne[T any](ctx context.Context, stmt postgres.Statement) (T, error) { query, args := stmt.Sql() + var result T row, err := PGInstance.PGXPool.Query(ctx, query, args...) if err != nil { - return nil, fmt.Errorf("execute query: %w", err) + return result, fmt.Errorf("execute query: %w", err) } - return pgx.CollectOneRow(row, pgx.RowToAddrOfStructByPos[T]) + var collected *T + collected, err = pgx.CollectOneRow(row, pgx.RowToAddrOfStructByPos[T]) + if err != nil || collected == nil { + return result, fmt.Errorf("collect row: %w", err) + } + return *collected, nil } -func ExecuteOneTx[T any](ctx context.Context, txn Tx, stmt postgres.Statement) (*T, error) { +func ExecuteOneTx[T any](ctx context.Context, txn Ex, stmt postgres.Statement) (T, error) { query, args := stmt.Sql() //result, err := scan.One(ctx, txn, scan.StructMapper[T](), query, args...) - rows, err := txn.Query(ctx, query, args...) + row, err := txn.Query(ctx, query, args...) + var result T if err != nil { - return nil, fmt.Errorf("txn query: %w", err) + return result, fmt.Errorf("txn query: %w", err) } - results, err := pgx.CollectRows(rows, pgx.RowToStructByName[T]) - if err != nil { - return nil, fmt.Errorf("collect rows: %w", err) + var collected *T + collected, err = pgx.CollectOneRow(row, pgx.RowToAddrOfStructByPos[T]) + if err != nil || collected == nil { + return result, fmt.Errorf("collect row: %w", err) } - if len(results) < 1 { - return nil, fmt.Errorf("no results") - } - return &results[0], err + return *collected, nil } -func ExecuteOneTxBob[T any](ctx context.Context, txn bob.Tx, stmt postgres.Statement) (*T, error) { +func ExecuteOneTxBob[T any](ctx context.Context, txn bob.Tx, stmt postgres.Statement) (T, error) { query, args := stmt.Sql() - result, err := scan.One(ctx, txn, scan.StructMapper[T](), query, args...) - return &result, err + return scan.One(ctx, txn, scan.StructMapper[T](), query, args...) } -func ExecuteMany[T any](ctx context.Context, stmt postgres.Statement) ([]*T, error) { +func ExecuteMany[T any](ctx context.Context, stmt postgres.Statement) ([]T, error) { query, args := stmt.Sql() rows, err := PGInstance.PGXPool.Query(ctx, query, args...) if err != nil { return nil, fmt.Errorf("execute query: %w", err) } - return pgx.CollectRows(rows, pgx.RowToAddrOfStructByPos[T]) + collected, err := pgx.CollectRows(rows, pgx.RowToAddrOfStructByPos[T]) + if err != nil { + return []T{}, fmt.Errorf("collect rows: %w", err) + } + results := make([]T, len(collected)) + for i, c := range collected { + if c == nil { + return results, fmt.Errorf("null collected") + } + results[i] = *c + } + return results, nil +} +func ExecuteManyTx[T any](ctx context.Context, txn Ex, stmt postgres.Statement) ([]T, error) { + query, args := stmt.Sql() + + rows, err := txn.Query(ctx, query, args...) + if err != nil { + return nil, fmt.Errorf("execute query: %w", err) + } + collected, err := pgx.CollectRows(rows, pgx.RowToAddrOfStructByPos[T]) + if err != nil { + return []T{}, fmt.Errorf("collect rows: %w", err) + } + results := make([]T, len(collected)) + for i, c := range collected { + if c == nil { + return results, fmt.Errorf("null collected") + } + results[i] = *c + } + return results, nil } func doMigrations(connection_string string) error { log.Debug().Str("dsn", connection_string).Msg("Connecting to database") @@ -166,15 +197,23 @@ func InitializeDatabase(ctx context.Context, uri string) error { log.Debug().Msg("No database migrations necessary") } - pgOnce.Do(func() { - db, e := pgxpool.New(ctx, uri) - bobDB := bob.NewDB(stdlib.OpenDBFromPool(db)) - PGInstance = &pginstance{bobDB, db} - err = e - }) + config, err := pgxpool.ParseConfig(uri) if err != nil { - return fmt.Errorf("unable to create connection pool: %w", err) + return fmt.Errorf("parse config: %w", err) } + config.AfterConnect = func(ctx2 context.Context, conn *pgx.Conn) error { + err2 := pgxgeom.Register(ctx, conn) + if err2 != nil { + return fmt.Errorf("pgxgeom register: %w", err2) + } + return nil + } + db, err := pgxpool.NewWithConfig(ctx, config) + if err != nil { + return fmt.Errorf("new pool: %w", err) + } + bobDB := bob.NewDB(stdlib.OpenDBFromPool(db)) + PGInstance = &pginstance{bobDB, db} var current string query := `SELECT current_database()` diff --git a/db/dberrors/communication_log_entry.bob.go b/db/dberrors/communication_log_entry.bob.go new file mode 100644 index 00000000..6d4833e1 --- /dev/null +++ b/db/dberrors/communication_log_entry.bob.go @@ -0,0 +1,17 @@ +// Code generated by BobGen psql v0.42.5. DO NOT EDIT. +// This file is meant to be re-generated in place and/or deleted at any time. + +package dberrors + +var CommunicationLogEntryErrors = &communicationLogEntryErrors{ + ErrUniqueCommunicationLogEntryPkey: &UniqueConstraintError{ + schema: "", + table: "communication_log_entry", + columns: []string{"id"}, + s: "communication_log_entry_pkey", + }, +} + +type communicationLogEntryErrors struct { + ErrUniqueCommunicationLogEntryPkey *UniqueConstraintError +} diff --git a/db/dbinfo/communication.bob.go b/db/dbinfo/communication.bob.go index 7560689d..faef2920 100644 --- a/db/dbinfo/communication.bob.go +++ b/db/dbinfo/communication.bob.go @@ -15,24 +15,6 @@ var Communications = Table[ Schema: "", Name: "communication", Columns: communicationColumns{ - Closed: column{ - Name: "closed", - DBType: "timestamp without time zone", - Default: "NULL", - Comment: "", - Nullable: true, - Generated: false, - AutoIncr: false, - }, - ClosedBy: column{ - Name: "closed_by", - DBType: "integer", - Default: "NULL", - Comment: "", - Nullable: true, - Generated: false, - AutoIncr: false, - }, Created: column{ Name: "created", DBType: "timestamp without time zone", @@ -51,42 +33,6 @@ var Communications = Table[ Generated: false, AutoIncr: false, }, - Invalidated: column{ - Name: "invalidated", - DBType: "timestamp without time zone", - Default: "NULL", - Comment: "", - Nullable: true, - Generated: false, - AutoIncr: false, - }, - InvalidatedBy: column{ - Name: "invalidated_by", - DBType: "integer", - Default: "NULL", - Comment: "", - Nullable: true, - Generated: false, - AutoIncr: false, - }, - Opened: column{ - Name: "opened", - DBType: "timestamp without time zone", - Default: "NULL", - Comment: "", - Nullable: true, - Generated: false, - AutoIncr: false, - }, - OpenedBy: column{ - Name: "opened_by", - DBType: "integer", - Default: "NULL", - Comment: "", - Nullable: true, - Generated: false, - AutoIncr: false, - }, OrganizationID: column{ Name: "organization_id", DBType: "integer", @@ -114,24 +60,6 @@ var Communications = Table[ Generated: false, AutoIncr: false, }, - SetPending: column{ - Name: "set_pending", - DBType: "timestamp without time zone", - Default: "NULL", - Comment: "", - Nullable: true, - Generated: false, - AutoIncr: false, - }, - SetPendingBy: column{ - Name: "set_pending_by", - DBType: "integer", - Default: "NULL", - Comment: "", - Nullable: true, - Generated: false, - AutoIncr: false, - }, SourceEmailLogID: column{ Name: "source_email_log_id", DBType: "integer", @@ -159,39 +87,12 @@ var Communications = Table[ Generated: false, AutoIncr: false, }, - SetPossibleIssue: column{ - Name: "set_possible_issue", - DBType: "timestamp without time zone", - Default: "NULL", + Status: column{ + Name: "status", + DBType: "public.communicationstatus", + Default: "", Comment: "", - Nullable: true, - Generated: false, - AutoIncr: false, - }, - SetPossibleIssueBy: column{ - Name: "set_possible_issue_by", - DBType: "integer", - Default: "NULL", - Comment: "", - Nullable: true, - Generated: false, - AutoIncr: false, - }, - SetPossibleResolved: column{ - Name: "set_possible_resolved", - DBType: "timestamp without time zone", - Default: "NULL", - Comment: "", - Nullable: true, - Generated: false, - AutoIncr: false, - }, - SetPossibleResolvedBy: column{ - Name: "set_possible_resolved_by", - DBType: "integer", - Default: "NULL", - Comment: "", - Nullable: true, + Nullable: false, Generated: false, AutoIncr: false, }, @@ -221,33 +122,6 @@ var Communications = Table[ Comment: "", }, ForeignKeys: communicationForeignKeys{ - CommunicationCommunicationClosedByFkey: foreignKey{ - constraint: constraint{ - Name: "communication.communication_closed_by_fkey", - Columns: []string{"closed_by"}, - Comment: "", - }, - ForeignTable: "user_", - ForeignColumns: []string{"id"}, - }, - CommunicationCommunicationInvalidatedByFkey: foreignKey{ - constraint: constraint{ - Name: "communication.communication_invalidated_by_fkey", - Columns: []string{"invalidated_by"}, - Comment: "", - }, - ForeignTable: "user_", - ForeignColumns: []string{"id"}, - }, - CommunicationCommunicationOpenedByFkey: foreignKey{ - constraint: constraint{ - Name: "communication.communication_opened_by_fkey", - Columns: []string{"opened_by"}, - Comment: "", - }, - ForeignTable: "user_", - ForeignColumns: []string{"id"}, - }, CommunicationCommunicationOrganizationIDFkey: foreignKey{ constraint: constraint{ Name: "communication.communication_organization_id_fkey", @@ -275,33 +149,6 @@ var Communications = Table[ ForeignTable: "comms.text_log", ForeignColumns: []string{"id"}, }, - CommunicationCommunicationSetPendingByFkey: foreignKey{ - constraint: constraint{ - Name: "communication.communication_set_pending_by_fkey", - Columns: []string{"set_pending_by"}, - Comment: "", - }, - ForeignTable: "user_", - ForeignColumns: []string{"id"}, - }, - CommunicationCommunicationSetPossibleIssueByFkey: foreignKey{ - constraint: constraint{ - Name: "communication.communication_set_possible_issue_by_fkey", - Columns: []string{"set_possible_issue_by"}, - Comment: "", - }, - ForeignTable: "user_", - ForeignColumns: []string{"id"}, - }, - CommunicationCommunicationSetPossibleResolvedByFkey: foreignKey{ - constraint: constraint{ - Name: "communication.communication_set_possible_resolved_by_fkey", - Columns: []string{"set_possible_resolved_by"}, - Comment: "", - }, - ForeignTable: "user_", - ForeignColumns: []string{"id"}, - }, CommunicationCommunicationSourceEmailLogIDFkey: foreignKey{ constraint: constraint{ Name: "communication.communication_source_email_log_id_fkey", @@ -335,31 +182,20 @@ var Communications = Table[ } type communicationColumns struct { - Closed column - ClosedBy column - Created column - ID column - Invalidated column - InvalidatedBy column - Opened column - OpenedBy column - OrganizationID column - ResponseEmailLogID column - ResponseTextLogID column - SetPending column - SetPendingBy column - SourceEmailLogID column - SourceReportID column - SourceTextLogID column - SetPossibleIssue column - SetPossibleIssueBy column - SetPossibleResolved column - SetPossibleResolvedBy column + Created column + ID column + OrganizationID column + ResponseEmailLogID column + ResponseTextLogID column + SourceEmailLogID column + SourceReportID column + SourceTextLogID column + Status column } func (c communicationColumns) AsSlice() []column { return []column{ - c.Closed, c.ClosedBy, c.Created, c.ID, c.Invalidated, c.InvalidatedBy, c.Opened, c.OpenedBy, c.OrganizationID, c.ResponseEmailLogID, c.ResponseTextLogID, c.SetPending, c.SetPendingBy, c.SourceEmailLogID, c.SourceReportID, c.SourceTextLogID, c.SetPossibleIssue, c.SetPossibleIssueBy, c.SetPossibleResolved, c.SetPossibleResolvedBy, + c.Created, c.ID, c.OrganizationID, c.ResponseEmailLogID, c.ResponseTextLogID, c.SourceEmailLogID, c.SourceReportID, c.SourceTextLogID, c.Status, } } @@ -374,23 +210,17 @@ func (i communicationIndexes) AsSlice() []index { } type communicationForeignKeys struct { - CommunicationCommunicationClosedByFkey foreignKey - CommunicationCommunicationInvalidatedByFkey foreignKey - CommunicationCommunicationOpenedByFkey foreignKey - CommunicationCommunicationOrganizationIDFkey foreignKey - CommunicationCommunicationResponseEmailLogIDFkey foreignKey - CommunicationCommunicationResponseTextLogIDFkey foreignKey - CommunicationCommunicationSetPendingByFkey foreignKey - CommunicationCommunicationSetPossibleIssueByFkey foreignKey - CommunicationCommunicationSetPossibleResolvedByFkey foreignKey - CommunicationCommunicationSourceEmailLogIDFkey foreignKey - CommunicationCommunicationSourceReportIDFkey foreignKey - CommunicationCommunicationSourceTextLogIDFkey foreignKey + CommunicationCommunicationOrganizationIDFkey foreignKey + CommunicationCommunicationResponseEmailLogIDFkey foreignKey + CommunicationCommunicationResponseTextLogIDFkey foreignKey + CommunicationCommunicationSourceEmailLogIDFkey foreignKey + CommunicationCommunicationSourceReportIDFkey foreignKey + CommunicationCommunicationSourceTextLogIDFkey foreignKey } func (f communicationForeignKeys) AsSlice() []foreignKey { return []foreignKey{ - f.CommunicationCommunicationClosedByFkey, f.CommunicationCommunicationInvalidatedByFkey, f.CommunicationCommunicationOpenedByFkey, f.CommunicationCommunicationOrganizationIDFkey, f.CommunicationCommunicationResponseEmailLogIDFkey, f.CommunicationCommunicationResponseTextLogIDFkey, f.CommunicationCommunicationSetPendingByFkey, f.CommunicationCommunicationSetPossibleIssueByFkey, f.CommunicationCommunicationSetPossibleResolvedByFkey, f.CommunicationCommunicationSourceEmailLogIDFkey, f.CommunicationCommunicationSourceReportIDFkey, f.CommunicationCommunicationSourceTextLogIDFkey, + f.CommunicationCommunicationOrganizationIDFkey, f.CommunicationCommunicationResponseEmailLogIDFkey, f.CommunicationCommunicationResponseTextLogIDFkey, f.CommunicationCommunicationSourceEmailLogIDFkey, f.CommunicationCommunicationSourceReportIDFkey, f.CommunicationCommunicationSourceTextLogIDFkey, } } diff --git a/db/dbinfo/communication_log_entry.bob.go b/db/dbinfo/communication_log_entry.bob.go new file mode 100644 index 00000000..e754be3c --- /dev/null +++ b/db/dbinfo/communication_log_entry.bob.go @@ -0,0 +1,157 @@ +// Code generated by BobGen psql v0.42.5. 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 CommunicationLogEntries = Table[ + communicationLogEntryColumns, + communicationLogEntryIndexes, + communicationLogEntryForeignKeys, + communicationLogEntryUniques, + communicationLogEntryChecks, +]{ + Schema: "", + Name: "communication_log_entry", + Columns: communicationLogEntryColumns{ + CommunicationID: column{ + Name: "communication_id", + DBType: "integer", + Default: "", + Comment: "", + Nullable: false, + Generated: false, + AutoIncr: false, + }, + Created: column{ + Name: "created", + DBType: "timestamp without time zone", + Default: "", + Comment: "", + Nullable: false, + Generated: false, + AutoIncr: false, + }, + ID: column{ + Name: "id", + DBType: "integer", + Default: "nextval('communication_log_entry_id_seq'::regclass)", + Comment: "", + Nullable: false, + Generated: false, + AutoIncr: false, + }, + Type: column{ + Name: "type_", + DBType: "public.communicationlogentry", + Default: "", + Comment: "", + Nullable: false, + Generated: false, + AutoIncr: false, + }, + User: column{ + Name: "user_", + DBType: "integer", + Default: "NULL", + Comment: "", + Nullable: true, + Generated: false, + AutoIncr: false, + }, + }, + Indexes: communicationLogEntryIndexes{ + CommunicationLogEntryPkey: index{ + Type: "btree", + Name: "communication_log_entry_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: "communication_log_entry_pkey", + Columns: []string{"id"}, + Comment: "", + }, + ForeignKeys: communicationLogEntryForeignKeys{ + CommunicationLogEntryCommunicationLogEntryCommunicationIDFkey: foreignKey{ + constraint: constraint{ + Name: "communication_log_entry.communication_log_entry_communication_id_fkey", + Columns: []string{"communication_id"}, + Comment: "", + }, + ForeignTable: "communication", + ForeignColumns: []string{"id"}, + }, + CommunicationLogEntryCommunicationLogEntryUserFkey: foreignKey{ + constraint: constraint{ + Name: "communication_log_entry.communication_log_entry_user__fkey", + Columns: []string{"user_"}, + Comment: "", + }, + ForeignTable: "user_", + ForeignColumns: []string{"id"}, + }, + }, + + Comment: "", +} + +type communicationLogEntryColumns struct { + CommunicationID column + Created column + ID column + Type column + User column +} + +func (c communicationLogEntryColumns) AsSlice() []column { + return []column{ + c.CommunicationID, c.Created, c.ID, c.Type, c.User, + } +} + +type communicationLogEntryIndexes struct { + CommunicationLogEntryPkey index +} + +func (i communicationLogEntryIndexes) AsSlice() []index { + return []index{ + i.CommunicationLogEntryPkey, + } +} + +type communicationLogEntryForeignKeys struct { + CommunicationLogEntryCommunicationLogEntryCommunicationIDFkey foreignKey + CommunicationLogEntryCommunicationLogEntryUserFkey foreignKey +} + +func (f communicationLogEntryForeignKeys) AsSlice() []foreignKey { + return []foreignKey{ + f.CommunicationLogEntryCommunicationLogEntryCommunicationIDFkey, f.CommunicationLogEntryCommunicationLogEntryUserFkey, + } +} + +type communicationLogEntryUniques struct{} + +func (u communicationLogEntryUniques) AsSlice() []constraint { + return []constraint{} +} + +type communicationLogEntryChecks struct{} + +func (c communicationLogEntryChecks) AsSlice() []check { + return []check{} +} diff --git a/db/dbinfo/publicreport.compliance.bob.go b/db/dbinfo/publicreport.compliance.bob.go index 559ce95f..6307c84b 100644 --- a/db/dbinfo/publicreport.compliance.bob.go +++ b/db/dbinfo/publicreport.compliance.bob.go @@ -62,7 +62,7 @@ var PublicreportCompliances = Table[ }, PermissionType: column{ Name: "permission_type", - DBType: "publicreport.permissionaccesstype", + DBType: "publicreport.permissionaccess", Default: "", Comment: "", Nullable: false, diff --git a/db/enums/enums.bob.go b/db/enums/enums.bob.go index f7b57f75..6578fd9c 100644 --- a/db/enums/enums.bob.go +++ b/db/enums/enums.bob.go @@ -582,6 +582,276 @@ func (e *CommsTextorigin) Scan(value any) error { return nil } +// Enum values for Communicationlogentry +const ( + CommunicationlogentryCreated Communicationlogentry = "created" + CommunicationlogentryStatusU2eclosed Communicationlogentry = "status.closed" + CommunicationlogentryStatusU2einvalidated Communicationlogentry = "status.invalidated" + CommunicationlogentryStatusU2eopened Communicationlogentry = "status.opened" + CommunicationlogentryStatusU2epending Communicationlogentry = "status.pending" + CommunicationlogentryStatusU2epossibleIssue Communicationlogentry = "status.possible-issue" + CommunicationlogentryStatusU2epossibleResolved Communicationlogentry = "status.possible-resolved" +) + +func AllCommunicationlogentry() []Communicationlogentry { + return []Communicationlogentry{ + CommunicationlogentryCreated, + CommunicationlogentryStatusU2eclosed, + CommunicationlogentryStatusU2einvalidated, + CommunicationlogentryStatusU2eopened, + CommunicationlogentryStatusU2epending, + CommunicationlogentryStatusU2epossibleIssue, + CommunicationlogentryStatusU2epossibleResolved, + } +} + +type Communicationlogentry string + +func (e Communicationlogentry) String() string { + return string(e) +} + +func (e Communicationlogentry) Valid() bool { + switch e { + case CommunicationlogentryCreated, + CommunicationlogentryStatusU2eclosed, + CommunicationlogentryStatusU2einvalidated, + CommunicationlogentryStatusU2eopened, + CommunicationlogentryStatusU2epending, + CommunicationlogentryStatusU2epossibleIssue, + CommunicationlogentryStatusU2epossibleResolved: + return true + default: + return false + } +} + +// useful when testing in other packages +func (e Communicationlogentry) All() []Communicationlogentry { + return AllCommunicationlogentry() +} + +func (e Communicationlogentry) MarshalText() ([]byte, error) { + return []byte(e), nil +} + +func (e *Communicationlogentry) UnmarshalText(text []byte) error { + return e.Scan(text) +} + +func (e Communicationlogentry) MarshalBinary() ([]byte, error) { + return []byte(e), nil +} + +func (e *Communicationlogentry) UnmarshalBinary(data []byte) error { + return e.Scan(data) +} + +func (e Communicationlogentry) Value() (driver.Value, error) { + return string(e), nil +} + +func (e *Communicationlogentry) Scan(value any) error { + switch x := value.(type) { + case string: + *e = Communicationlogentry(x) + case []byte: + *e = Communicationlogentry(x) + case nil: + return fmt.Errorf("cannot nil into Communicationlogentry") + default: + return fmt.Errorf("cannot scan type %T: %v", value, value) + } + + if !e.Valid() { + return fmt.Errorf("invalid Communicationlogentry value: %s", *e) + } + + return nil +} + +// Enum values for Communicationstatus +const ( + CommunicationstatusClosed Communicationstatus = "closed" + CommunicationstatusInvalid Communicationstatus = "invalid" + CommunicationstatusNew Communicationstatus = "new" + CommunicationstatusOpened Communicationstatus = "opened" + CommunicationstatusPending Communicationstatus = "pending" + CommunicationstatusPossibleIssue Communicationstatus = "possible-issue" + CommunicationstatusPossibleResolved Communicationstatus = "possible-resolved" + CommunicationstatusResolved Communicationstatus = "resolved" +) + +func AllCommunicationstatus() []Communicationstatus { + return []Communicationstatus{ + CommunicationstatusClosed, + CommunicationstatusInvalid, + CommunicationstatusNew, + CommunicationstatusOpened, + CommunicationstatusPending, + CommunicationstatusPossibleIssue, + CommunicationstatusPossibleResolved, + CommunicationstatusResolved, + } +} + +type Communicationstatus string + +func (e Communicationstatus) String() string { + return string(e) +} + +func (e Communicationstatus) Valid() bool { + switch e { + case CommunicationstatusClosed, + CommunicationstatusInvalid, + CommunicationstatusNew, + CommunicationstatusOpened, + CommunicationstatusPending, + CommunicationstatusPossibleIssue, + CommunicationstatusPossibleResolved, + CommunicationstatusResolved: + return true + default: + return false + } +} + +// useful when testing in other packages +func (e Communicationstatus) All() []Communicationstatus { + return AllCommunicationstatus() +} + +func (e Communicationstatus) MarshalText() ([]byte, error) { + return []byte(e), nil +} + +func (e *Communicationstatus) UnmarshalText(text []byte) error { + return e.Scan(text) +} + +func (e Communicationstatus) MarshalBinary() ([]byte, error) { + return []byte(e), nil +} + +func (e *Communicationstatus) UnmarshalBinary(data []byte) error { + return e.Scan(data) +} + +func (e Communicationstatus) Value() (driver.Value, error) { + return string(e), nil +} + +func (e *Communicationstatus) Scan(value any) error { + switch x := value.(type) { + case string: + *e = Communicationstatus(x) + case []byte: + *e = Communicationstatus(x) + case nil: + return fmt.Errorf("cannot nil into Communicationstatus") + default: + return fmt.Errorf("cannot scan type %T: %v", value, value) + } + + if !e.Valid() { + return fmt.Errorf("invalid Communicationstatus value: %s", *e) + } + + return nil +} + +// Enum values for Communicationstatustype +const ( + CommunicationstatustypeClosed Communicationstatustype = "closed" + CommunicationstatustypeInvalid Communicationstatustype = "invalid" + CommunicationstatustypeNew Communicationstatustype = "new" + CommunicationstatustypeOpened Communicationstatustype = "opened" + CommunicationstatustypePending Communicationstatustype = "pending" + CommunicationstatustypePossibleIssue Communicationstatustype = "possible-issue" + CommunicationstatustypePossibleResolved Communicationstatustype = "possible-resolved" + CommunicationstatustypeResolved Communicationstatustype = "resolved" +) + +func AllCommunicationstatustype() []Communicationstatustype { + return []Communicationstatustype{ + CommunicationstatustypeClosed, + CommunicationstatustypeInvalid, + CommunicationstatustypeNew, + CommunicationstatustypeOpened, + CommunicationstatustypePending, + CommunicationstatustypePossibleIssue, + CommunicationstatustypePossibleResolved, + CommunicationstatustypeResolved, + } +} + +type Communicationstatustype string + +func (e Communicationstatustype) String() string { + return string(e) +} + +func (e Communicationstatustype) Valid() bool { + switch e { + case CommunicationstatustypeClosed, + CommunicationstatustypeInvalid, + CommunicationstatustypeNew, + CommunicationstatustypeOpened, + CommunicationstatustypePending, + CommunicationstatustypePossibleIssue, + CommunicationstatustypePossibleResolved, + CommunicationstatustypeResolved: + return true + default: + return false + } +} + +// useful when testing in other packages +func (e Communicationstatustype) All() []Communicationstatustype { + return AllCommunicationstatustype() +} + +func (e Communicationstatustype) MarshalText() ([]byte, error) { + return []byte(e), nil +} + +func (e *Communicationstatustype) UnmarshalText(text []byte) error { + return e.Scan(text) +} + +func (e Communicationstatustype) MarshalBinary() ([]byte, error) { + return []byte(e), nil +} + +func (e *Communicationstatustype) UnmarshalBinary(data []byte) error { + return e.Scan(data) +} + +func (e Communicationstatustype) Value() (driver.Value, error) { + return string(e), nil +} + +func (e *Communicationstatustype) Scan(value any) error { + switch x := value.(type) { + case string: + *e = Communicationstatustype(x) + case []byte: + *e = Communicationstatustype(x) + case nil: + return fmt.Errorf("cannot nil into Communicationstatustype") + default: + return fmt.Errorf("cannot scan type %T: %v", value, value) + } + + if !e.Valid() { + return fmt.Errorf("invalid Communicationstatustype value: %s", *e) + } + + return nil +} + // Enum values for FileuploadCsvtype const ( FileuploadCsvtypePoollist FileuploadCsvtype = "PoolList" @@ -1550,35 +1820,35 @@ func (e *PublicreportNuisancedurationtype) Scan(value any) error { return nil } -// Enum values for PublicreportPermissionaccesstype +// Enum values for PublicreportPermissionaccess const ( - PublicreportPermissionaccesstypeDenied PublicreportPermissionaccesstype = "denied" - PublicreportPermissionaccesstypeGranted PublicreportPermissionaccesstype = "granted" - PublicreportPermissionaccesstypeUnselected PublicreportPermissionaccesstype = "unselected" - PublicreportPermissionaccesstypeWithOwner PublicreportPermissionaccesstype = "with-owner" + PublicreportPermissionaccessDenied PublicreportPermissionaccess = "denied" + PublicreportPermissionaccessGranted PublicreportPermissionaccess = "granted" + PublicreportPermissionaccessUnselected PublicreportPermissionaccess = "unselected" + PublicreportPermissionaccessWithOwner PublicreportPermissionaccess = "with-owner" ) -func AllPublicreportPermissionaccesstype() []PublicreportPermissionaccesstype { - return []PublicreportPermissionaccesstype{ - PublicreportPermissionaccesstypeDenied, - PublicreportPermissionaccesstypeGranted, - PublicreportPermissionaccesstypeUnselected, - PublicreportPermissionaccesstypeWithOwner, +func AllPublicreportPermissionaccess() []PublicreportPermissionaccess { + return []PublicreportPermissionaccess{ + PublicreportPermissionaccessDenied, + PublicreportPermissionaccessGranted, + PublicreportPermissionaccessUnselected, + PublicreportPermissionaccessWithOwner, } } -type PublicreportPermissionaccesstype string +type PublicreportPermissionaccess string -func (e PublicreportPermissionaccesstype) String() string { +func (e PublicreportPermissionaccess) String() string { return string(e) } -func (e PublicreportPermissionaccesstype) Valid() bool { +func (e PublicreportPermissionaccess) Valid() bool { switch e { - case PublicreportPermissionaccesstypeDenied, - PublicreportPermissionaccesstypeGranted, - PublicreportPermissionaccesstypeUnselected, - PublicreportPermissionaccesstypeWithOwner: + case PublicreportPermissionaccessDenied, + PublicreportPermissionaccessGranted, + PublicreportPermissionaccessUnselected, + PublicreportPermissionaccessWithOwner: return true default: return false @@ -1586,44 +1856,44 @@ func (e PublicreportPermissionaccesstype) Valid() bool { } // useful when testing in other packages -func (e PublicreportPermissionaccesstype) All() []PublicreportPermissionaccesstype { - return AllPublicreportPermissionaccesstype() +func (e PublicreportPermissionaccess) All() []PublicreportPermissionaccess { + return AllPublicreportPermissionaccess() } -func (e PublicreportPermissionaccesstype) MarshalText() ([]byte, error) { +func (e PublicreportPermissionaccess) MarshalText() ([]byte, error) { return []byte(e), nil } -func (e *PublicreportPermissionaccesstype) UnmarshalText(text []byte) error { +func (e *PublicreportPermissionaccess) UnmarshalText(text []byte) error { return e.Scan(text) } -func (e PublicreportPermissionaccesstype) MarshalBinary() ([]byte, error) { +func (e PublicreportPermissionaccess) MarshalBinary() ([]byte, error) { return []byte(e), nil } -func (e *PublicreportPermissionaccesstype) UnmarshalBinary(data []byte) error { +func (e *PublicreportPermissionaccess) UnmarshalBinary(data []byte) error { return e.Scan(data) } -func (e PublicreportPermissionaccesstype) Value() (driver.Value, error) { +func (e PublicreportPermissionaccess) Value() (driver.Value, error) { return string(e), nil } -func (e *PublicreportPermissionaccesstype) Scan(value any) error { +func (e *PublicreportPermissionaccess) Scan(value any) error { switch x := value.(type) { case string: - *e = PublicreportPermissionaccesstype(x) + *e = PublicreportPermissionaccess(x) case []byte: - *e = PublicreportPermissionaccesstype(x) + *e = PublicreportPermissionaccess(x) case nil: - return fmt.Errorf("cannot nil into PublicreportPermissionaccesstype") + return fmt.Errorf("cannot nil into PublicreportPermissionaccess") default: return fmt.Errorf("cannot scan type %T: %v", value, value) } if !e.Valid() { - return fmt.Errorf("invalid PublicreportPermissionaccesstype value: %s", *e) + return fmt.Errorf("invalid PublicreportPermissionaccess value: %s", *e) } return nil diff --git a/db/jet/main.go b/db/jet/main.go index 5f52cb1f..b4cf122c 100644 --- a/db/jet/main.go +++ b/db/jet/main.go @@ -5,12 +5,12 @@ import ( "log" "os" - "github.com/Gleipnir-Technology/nidus-sync/db/types" "github.com/go-jet/jet/v2/generator/metadata" genpostgres "github.com/go-jet/jet/v2/generator/postgres" "github.com/go-jet/jet/v2/generator/template" "github.com/go-jet/jet/v2/postgres" _ "github.com/lib/pq" + "github.com/twpayne/go-geom" ) var schemas []string = []string{ @@ -20,19 +20,53 @@ var schemas []string = []string{ "stadia", } +func customTableSQLBuilderColumn(dialect template.Dialect, column metadata.Column) template.TableSQLBuilderColumn { + defaultColumn := template.DefaultTableSQLBuilderColumn(dialect, column) + /* + if defaultColumn.Name == "Location" { + log.Printf("current location column: name '%s' type '%s'", defaultColumn.Name, defaultColumn.Type) + defaultColumn.Import = "github.com/Gleipnir-Technology/nidus-sync/db/column" + defaultColumn.PackageName = "column" + defaultColumn.Type = "ColumnGeometry" + defaultColumn.TypeFactory = "GeometryColumn" + } + */ + return defaultColumn +} +func customTableSQLBuilder(table metadata.Table) template.TableSQLBuilder { + builder := template.DefaultTableSQLBuilder(table).UseColumn(customTableSQLBuilderColumn) + log.Printf("table sql builder: path '%s' filename '%s' instancename '%s' typename '%s' defaultalias '%s'", builder.Path, builder.FileName, builder.InstanceName, builder.TypeName, builder.DefaultAlias) + builder.Imports = []string{"github.com/Gleipnir-Technology/nidus-sync/db/column"} + return builder +} +func customTableModelField(column metadata.Column) template.TableModelField { + defaultTableModelField := template.DefaultTableModelField(column) + //log.Printf("'%s' '%s' '%s'", table.Name, column.Name, column.DataType.Name) + if column.Name == "extent" && column.DataType.Name == "box2d" { + defaultTableModelField.Type = template.NewType(geom.Bounds{}) + } else if column.DataType.Name == "geometry" { + name := "geom.T" + if column.IsNullable { + name = "*geom.T" + } + geom_type := template.Type{ + ImportPath: "github.com/twpayne/go-geom", + AdditionalImportPaths: []string{}, + Name: name, + } + defaultTableModelField.Type = geom_type + } + return defaultTableModelField +} +func customTableModel(table metadata.Table) template.TableModel { + return template.DefaultTableModel(table).UseField(customTableModelField) +} func customTemplate() template.Template { return template.Default(postgres.Dialect).UseSchema(func(schema metadata.Schema) template.Schema { - return template.DefaultSchema(schema).UseModel(template.DefaultModel().UseTable(func(table metadata.Table) template.TableModel { - return template.DefaultTableModel(table).UseField(func(column metadata.Column) template.TableModelField { - defaultTableModelField := template.DefaultTableModelField(column) - //log.Printf("'%s' '%s' '%s'", table.Name, column.Name, column.DataType.Name) - if column.Name == "extent" && column.DataType.Name == "box2d" { - defaultTableModelField.Type = template.NewType(types.Box2D{}) - } - return defaultTableModelField - }) - }), - ) + customSchema := template.DefaultSchema(schema) + customSchema = customSchema.UseModel(template.DefaultModel().UseTable(customTableModel)) + customSchema = customSchema.UseSQLBuilder(template.DefaultSQLBuilder().UseTable(customTableSQLBuilder)) + return customSchema }) } diff --git a/db/migrations/00147_communication.sql b/db/migrations/00147_communication.sql index db994cb5..88049825 100644 --- a/db/migrations/00147_communication.sql +++ b/db/migrations/00147_communication.sql @@ -1,22 +1,44 @@ -- +goose Up +CREATE TYPE CommunicationStatus AS ENUM ( + 'closed', + 'invalid', + 'new', + 'opened', + 'pending', + 'possible-issue', + 'possible-resolved', + 'resolved' +); CREATE TABLE communication ( - closed TIMESTAMP WITHOUT TIME ZONE, - closed_by INTEGER REFERENCES user_(id), created TIMESTAMP WITHOUT TIME ZONE NOT NULL, id SERIAL, - invalidated TIMESTAMP WITHOUT TIME ZONE, - invalidated_by INTEGER REFERENCES user_(id), - opened TIMESTAMP WITHOUT TIME ZONE, - opened_by INTEGER REFERENCES user_(id), organization_id INTEGER NOT NULL REFERENCES organization(id), response_email_log_id INTEGER REFERENCES comms.email_log(id), response_text_log_id INTEGER REFERENCES comms.text_log(id), - set_pending TIMESTAMP WITHOUT TIME ZONE, - set_pending_by INTEGER REFERENCES user_(id), source_email_log_id INTEGER REFERENCES comms.email_log(id), source_report_id INTEGER REFERENCES publicreport.report(id), source_text_log_id INTEGER REFERENCES comms.text_log(id), + status CommunicationStatus NOT NULL, + PRIMARY KEY(id) +); +CREATE TYPE CommunicationLogEntry AS ENUM ( + 'created', + 'status.closed', + 'status.invalidated', + 'status.opened', + 'status.pending', + 'status.possible-issue', + 'status.possible-resolved' +); +CREATE TABLE communication_log_entry ( + communication_id INTEGER NOT NULL REFERENCES communication(id), + created TIMESTAMP WITHOUT TIME ZONE NOT NULL, + id SERIAL, + type_ CommunicationLogEntry NOT NULL, + user_ INTEGER REFERENCES user_(id), PRIMARY KEY(id) ); -- +goose Down DROP TABLE communication; +DROP TABLE communication_log_entry; +DROP TYPE CommunicationLogEntry; diff --git a/db/migrations/00148_communications_from_reports.sql b/db/migrations/00148_communications_from_reports.sql index 21841263..3f86f85d 100644 --- a/db/migrations/00148_communications_from_reports.sql +++ b/db/migrations/00148_communications_from_reports.sql @@ -1,37 +1,36 @@ -- +goose Up INSERT INTO communication ( - closed, - closed_by, created, --id, - invalidated, - invalidated_by, - opened, - opened_by, organization_id, response_email_log_id, response_text_log_id, - set_pending, - set_pending_by, source_email_log_id, source_report_id, - source_text_log_id + source_text_log_id, + status ) SELECT - NULL, - NULL, created, - NULL, - NULL, - NULL, - NULL, organization_id, NULL, NULL, NULL, - NULL, - NULL, id, - NULL + NULL, + 'new' FROM publicreport.report; +INSERT INTO communication_log_entry ( + communication_id, + created, + --id, + type_, + user_ +) SELECT + id, + created, + 'created', + NULL +FROM communication; -- +goose Down +DELETE FROM communication_log_entry; DELETE FROM communication; diff --git a/db/migrations/00149_permissionaccesstype.sql b/db/migrations/00149_permissionaccesstype.sql index 9d07d5d6..4454e779 100644 --- a/db/migrations/00149_permissionaccesstype.sql +++ b/db/migrations/00149_permissionaccesstype.sql @@ -1,5 +1,5 @@ -- +goose Up -CREATE TYPE publicreport.PermissionAccessType AS ENUM ( +CREATE TYPE publicreport.PermissionAccess AS ENUM ( 'denied', 'granted', 'unselected', @@ -7,7 +7,7 @@ CREATE TYPE publicreport.PermissionAccessType AS ENUM ( ); ALTER TABLE publicreport.compliance ALTER COLUMN permission_type - TYPE publicreport.PermissionAccessType USING permission_type::text::publicreport.PermissionAccessType; + TYPE publicreport.PermissionAccess USING permission_type::text::publicreport.PermissionAccess; DROP TYPE PermissionAccessType; -- +goose Down CREATE TYPE PermissionAccessType AS ENUM ( @@ -18,5 +18,5 @@ CREATE TYPE PermissionAccessType AS ENUM ( ); ALTER TABLE publicreport.compliance ALTER COLUMN permission_type - TYPE PermissionAccessType; + TYPE PermissionAccessType USING permission_type::text::PermissionAccessType; DROP TYPE publicreport.PermissionAccessType; diff --git a/db/migrations/00150_communication_possible_status.sql b/db/migrations/00150_communication_possible_status.sql deleted file mode 100644 index 912a2594..00000000 --- a/db/migrations/00150_communication_possible_status.sql +++ /dev/null @@ -1,6 +0,0 @@ --- +goose Up -ALTER TABLE communication - ADD COLUMN set_possible_issue TIMESTAMP WITHOUT TIME ZONE, - ADD COLUMN set_possible_issue_by INTEGER REFERENCES user_(id), - ADD COLUMN set_possible_resolved TIMESTAMP WITHOUT TIME ZONE, - ADD COLUMN set_possible_resolved_by INTEGER REFERENCES user_(id); diff --git a/db/models/bob_loaders.bob.go b/db/models/bob_loaders.bob.go index 7b35b588..18986dee 100644 --- a/db/models/bob_loaders.bob.go +++ b/db/models/bob_loaders.bob.go @@ -26,6 +26,7 @@ type preloaders struct { CommsTextJob commsTextJobPreloader CommsTextLog commsTextLogPreloader Communication communicationPreloader + CommunicationLogEntry communicationLogEntryPreloader ComplianceReportRequest complianceReportRequestPreloader ComplianceReportRequestMailer complianceReportRequestMailerPreloader DistrictSubscriptionEmail districtSubscriptionEmailPreloader @@ -120,6 +121,7 @@ func getPreloaders() preloaders { CommsTextJob: buildCommsTextJobPreloader(), CommsTextLog: buildCommsTextLogPreloader(), Communication: buildCommunicationPreloader(), + CommunicationLogEntry: buildCommunicationLogEntryPreloader(), ComplianceReportRequest: buildComplianceReportRequestPreloader(), ComplianceReportRequestMailer: buildComplianceReportRequestMailerPreloader(), DistrictSubscriptionEmail: buildDistrictSubscriptionEmailPreloader(), @@ -220,6 +222,7 @@ type thenLoaders[Q orm.Loadable] struct { CommsTextJob commsTextJobThenLoader[Q] CommsTextLog commsTextLogThenLoader[Q] Communication communicationThenLoader[Q] + CommunicationLogEntry communicationLogEntryThenLoader[Q] ComplianceReportRequest complianceReportRequestThenLoader[Q] ComplianceReportRequestMailer complianceReportRequestMailerThenLoader[Q] DistrictSubscriptionEmail districtSubscriptionEmailThenLoader[Q] @@ -314,6 +317,7 @@ func getThenLoaders[Q orm.Loadable]() thenLoaders[Q] { CommsTextJob: buildCommsTextJobThenLoader[Q](), CommsTextLog: buildCommsTextLogThenLoader[Q](), Communication: buildCommunicationThenLoader[Q](), + CommunicationLogEntry: buildCommunicationLogEntryThenLoader[Q](), ComplianceReportRequest: buildComplianceReportRequestThenLoader[Q](), ComplianceReportRequestMailer: buildComplianceReportRequestMailerThenLoader[Q](), DistrictSubscriptionEmail: buildDistrictSubscriptionEmailThenLoader[Q](), diff --git a/db/models/bob_where.bob.go b/db/models/bob_where.bob.go index d86c6277..7ec2091b 100644 --- a/db/models/bob_where.bob.go +++ b/db/models/bob_where.bob.go @@ -26,6 +26,7 @@ func Where[Q psql.Filterable]() struct { CommsTextJobs commsTextJobWhere[Q] CommsTextLogs commsTextLogWhere[Q] Communications communicationWhere[Q] + CommunicationLogEntries communicationLogEntryWhere[Q] ComplianceReportRequests complianceReportRequestWhere[Q] ComplianceReportRequestMailers complianceReportRequestMailerWhere[Q] DistrictSubscriptionEmails districtSubscriptionEmailWhere[Q] @@ -128,6 +129,7 @@ func Where[Q psql.Filterable]() struct { CommsTextJobs commsTextJobWhere[Q] CommsTextLogs commsTextLogWhere[Q] Communications communicationWhere[Q] + CommunicationLogEntries communicationLogEntryWhere[Q] ComplianceReportRequests complianceReportRequestWhere[Q] ComplianceReportRequestMailers complianceReportRequestMailerWhere[Q] DistrictSubscriptionEmails districtSubscriptionEmailWhere[Q] @@ -229,6 +231,7 @@ func Where[Q psql.Filterable]() struct { CommsTextJobs: buildCommsTextJobWhere[Q](CommsTextJobs.Columns), CommsTextLogs: buildCommsTextLogWhere[Q](CommsTextLogs.Columns), Communications: buildCommunicationWhere[Q](Communications.Columns), + CommunicationLogEntries: buildCommunicationLogEntryWhere[Q](CommunicationLogEntries.Columns), ComplianceReportRequests: buildComplianceReportRequestWhere[Q](ComplianceReportRequests.Columns), ComplianceReportRequestMailers: buildComplianceReportRequestMailerWhere[Q](ComplianceReportRequestMailers.Columns), DistrictSubscriptionEmails: buildDistrictSubscriptionEmailWhere[Q](DistrictSubscriptionEmails.Columns), diff --git a/db/models/communication.bob.go b/db/models/communication.bob.go index 4b95bce5..fa036cd9 100644 --- a/db/models/communication.bob.go +++ b/db/models/communication.bob.go @@ -18,6 +18,7 @@ import ( "github.com/Gleipnir-Technology/bob/expr" "github.com/Gleipnir-Technology/bob/orm" "github.com/Gleipnir-Technology/bob/types/pgtypes" + enums "github.com/Gleipnir-Technology/nidus-sync/db/enums" "github.com/aarondl/opt/null" "github.com/aarondl/opt/omit" "github.com/aarondl/opt/omitnull" @@ -25,26 +26,15 @@ import ( // Communication is an object representing the database table. type Communication struct { - Closed null.Val[time.Time] `db:"closed" ` - ClosedBy null.Val[int32] `db:"closed_by" ` - Created time.Time `db:"created" ` - ID int32 `db:"id,pk" ` - Invalidated null.Val[time.Time] `db:"invalidated" ` - InvalidatedBy null.Val[int32] `db:"invalidated_by" ` - Opened null.Val[time.Time] `db:"opened" ` - OpenedBy null.Val[int32] `db:"opened_by" ` - OrganizationID int32 `db:"organization_id" ` - ResponseEmailLogID null.Val[int32] `db:"response_email_log_id" ` - ResponseTextLogID null.Val[int32] `db:"response_text_log_id" ` - SetPending null.Val[time.Time] `db:"set_pending" ` - SetPendingBy null.Val[int32] `db:"set_pending_by" ` - SourceEmailLogID null.Val[int32] `db:"source_email_log_id" ` - SourceReportID null.Val[int32] `db:"source_report_id" ` - SourceTextLogID null.Val[int32] `db:"source_text_log_id" ` - SetPossibleIssue null.Val[time.Time] `db:"set_possible_issue" ` - SetPossibleIssueBy null.Val[int32] `db:"set_possible_issue_by" ` - SetPossibleResolved null.Val[time.Time] `db:"set_possible_resolved" ` - SetPossibleResolvedBy null.Val[int32] `db:"set_possible_resolved_by" ` + Created time.Time `db:"created" ` + ID int32 `db:"id,pk" ` + OrganizationID int32 `db:"organization_id" ` + ResponseEmailLogID null.Val[int32] `db:"response_email_log_id" ` + ResponseTextLogID null.Val[int32] `db:"response_text_log_id" ` + SourceEmailLogID null.Val[int32] `db:"source_email_log_id" ` + SourceReportID null.Val[int32] `db:"source_report_id" ` + SourceTextLogID null.Val[int32] `db:"source_text_log_id" ` + Status enums.Communicationstatus `db:"status" ` R communicationR `db:"-" ` } @@ -61,72 +51,45 @@ type CommunicationsQuery = *psql.ViewQuery[*Communication, CommunicationSlice] // communicationR is where relationships are stored. type communicationR struct { - ClosedByUser *User // communication.communication_closed_by_fkey - InvalidatedByUser *User // communication.communication_invalidated_by_fkey - OpenedByUser *User // communication.communication_opened_by_fkey - Organization *Organization // communication.communication_organization_id_fkey - ResponseEmailLogEmailLog *CommsEmailLog // communication.communication_response_email_log_id_fkey - ResponseTextLogTextLog *CommsTextLog // communication.communication_response_text_log_id_fkey - SetPendingByUser *User // communication.communication_set_pending_by_fkey - SetPossibleIssueByUser *User // communication.communication_set_possible_issue_by_fkey - SetPossibleResolvedByUser *User // communication.communication_set_possible_resolved_by_fkey - SourceEmailLogEmailLog *CommsEmailLog // communication.communication_source_email_log_id_fkey - SourceReportReport *PublicreportReport // communication.communication_source_report_id_fkey - SourceTextLogTextLog *CommsTextLog // communication.communication_source_text_log_id_fkey + Organization *Organization // communication.communication_organization_id_fkey + ResponseEmailLogEmailLog *CommsEmailLog // communication.communication_response_email_log_id_fkey + ResponseTextLogTextLog *CommsTextLog // communication.communication_response_text_log_id_fkey + SourceEmailLogEmailLog *CommsEmailLog // communication.communication_source_email_log_id_fkey + SourceReportReport *PublicreportReport // communication.communication_source_report_id_fkey + SourceTextLogTextLog *CommsTextLog // communication.communication_source_text_log_id_fkey + CommunicationLogEntries CommunicationLogEntrySlice // communication_log_entry.communication_log_entry_communication_id_fkey } func buildCommunicationColumns(alias string) communicationColumns { return communicationColumns{ ColumnsExpr: expr.NewColumnsExpr( - "closed", "closed_by", "created", "id", "invalidated", "invalidated_by", "opened", "opened_by", "organization_id", "response_email_log_id", "response_text_log_id", "set_pending", "set_pending_by", "source_email_log_id", "source_report_id", "source_text_log_id", "set_possible_issue", "set_possible_issue_by", "set_possible_resolved", "set_possible_resolved_by", + "created", "id", "organization_id", "response_email_log_id", "response_text_log_id", "source_email_log_id", "source_report_id", "source_text_log_id", "status", ).WithParent("communication"), - tableAlias: alias, - Closed: psql.Quote(alias, "closed"), - ClosedBy: psql.Quote(alias, "closed_by"), - Created: psql.Quote(alias, "created"), - ID: psql.Quote(alias, "id"), - Invalidated: psql.Quote(alias, "invalidated"), - InvalidatedBy: psql.Quote(alias, "invalidated_by"), - Opened: psql.Quote(alias, "opened"), - OpenedBy: psql.Quote(alias, "opened_by"), - OrganizationID: psql.Quote(alias, "organization_id"), - ResponseEmailLogID: psql.Quote(alias, "response_email_log_id"), - ResponseTextLogID: psql.Quote(alias, "response_text_log_id"), - SetPending: psql.Quote(alias, "set_pending"), - SetPendingBy: psql.Quote(alias, "set_pending_by"), - SourceEmailLogID: psql.Quote(alias, "source_email_log_id"), - SourceReportID: psql.Quote(alias, "source_report_id"), - SourceTextLogID: psql.Quote(alias, "source_text_log_id"), - SetPossibleIssue: psql.Quote(alias, "set_possible_issue"), - SetPossibleIssueBy: psql.Quote(alias, "set_possible_issue_by"), - SetPossibleResolved: psql.Quote(alias, "set_possible_resolved"), - SetPossibleResolvedBy: psql.Quote(alias, "set_possible_resolved_by"), + tableAlias: alias, + Created: psql.Quote(alias, "created"), + ID: psql.Quote(alias, "id"), + OrganizationID: psql.Quote(alias, "organization_id"), + ResponseEmailLogID: psql.Quote(alias, "response_email_log_id"), + ResponseTextLogID: psql.Quote(alias, "response_text_log_id"), + SourceEmailLogID: psql.Quote(alias, "source_email_log_id"), + SourceReportID: psql.Quote(alias, "source_report_id"), + SourceTextLogID: psql.Quote(alias, "source_text_log_id"), + Status: psql.Quote(alias, "status"), } } type communicationColumns struct { expr.ColumnsExpr - tableAlias string - Closed psql.Expression - ClosedBy psql.Expression - Created psql.Expression - ID psql.Expression - Invalidated psql.Expression - InvalidatedBy psql.Expression - Opened psql.Expression - OpenedBy psql.Expression - OrganizationID psql.Expression - ResponseEmailLogID psql.Expression - ResponseTextLogID psql.Expression - SetPending psql.Expression - SetPendingBy psql.Expression - SourceEmailLogID psql.Expression - SourceReportID psql.Expression - SourceTextLogID psql.Expression - SetPossibleIssue psql.Expression - SetPossibleIssueBy psql.Expression - SetPossibleResolved psql.Expression - SetPossibleResolvedBy psql.Expression + tableAlias string + Created psql.Expression + ID psql.Expression + OrganizationID psql.Expression + ResponseEmailLogID psql.Expression + ResponseTextLogID psql.Expression + SourceEmailLogID psql.Expression + SourceReportID psql.Expression + SourceTextLogID psql.Expression + Status psql.Expression } func (c communicationColumns) Alias() string { @@ -141,54 +104,25 @@ func (communicationColumns) AliasedAs(alias string) communicationColumns { // All values are optional, and do not have to be set // Generated columns are not included type CommunicationSetter struct { - Closed omitnull.Val[time.Time] `db:"closed" ` - ClosedBy omitnull.Val[int32] `db:"closed_by" ` - Created omit.Val[time.Time] `db:"created" ` - ID omit.Val[int32] `db:"id,pk" ` - Invalidated omitnull.Val[time.Time] `db:"invalidated" ` - InvalidatedBy omitnull.Val[int32] `db:"invalidated_by" ` - Opened omitnull.Val[time.Time] `db:"opened" ` - OpenedBy omitnull.Val[int32] `db:"opened_by" ` - OrganizationID omit.Val[int32] `db:"organization_id" ` - ResponseEmailLogID omitnull.Val[int32] `db:"response_email_log_id" ` - ResponseTextLogID omitnull.Val[int32] `db:"response_text_log_id" ` - SetPending omitnull.Val[time.Time] `db:"set_pending" ` - SetPendingBy omitnull.Val[int32] `db:"set_pending_by" ` - SourceEmailLogID omitnull.Val[int32] `db:"source_email_log_id" ` - SourceReportID omitnull.Val[int32] `db:"source_report_id" ` - SourceTextLogID omitnull.Val[int32] `db:"source_text_log_id" ` - SetPossibleIssue omitnull.Val[time.Time] `db:"set_possible_issue" ` - SetPossibleIssueBy omitnull.Val[int32] `db:"set_possible_issue_by" ` - SetPossibleResolved omitnull.Val[time.Time] `db:"set_possible_resolved" ` - SetPossibleResolvedBy omitnull.Val[int32] `db:"set_possible_resolved_by" ` + Created omit.Val[time.Time] `db:"created" ` + ID omit.Val[int32] `db:"id,pk" ` + OrganizationID omit.Val[int32] `db:"organization_id" ` + ResponseEmailLogID omitnull.Val[int32] `db:"response_email_log_id" ` + ResponseTextLogID omitnull.Val[int32] `db:"response_text_log_id" ` + SourceEmailLogID omitnull.Val[int32] `db:"source_email_log_id" ` + SourceReportID omitnull.Val[int32] `db:"source_report_id" ` + SourceTextLogID omitnull.Val[int32] `db:"source_text_log_id" ` + Status omit.Val[enums.Communicationstatus] `db:"status" ` } func (s CommunicationSetter) SetColumns() []string { - vals := make([]string, 0, 20) - if !s.Closed.IsUnset() { - vals = append(vals, "closed") - } - if !s.ClosedBy.IsUnset() { - vals = append(vals, "closed_by") - } + vals := make([]string, 0, 9) if s.Created.IsValue() { vals = append(vals, "created") } if s.ID.IsValue() { vals = append(vals, "id") } - if !s.Invalidated.IsUnset() { - vals = append(vals, "invalidated") - } - if !s.InvalidatedBy.IsUnset() { - vals = append(vals, "invalidated_by") - } - if !s.Opened.IsUnset() { - vals = append(vals, "opened") - } - if !s.OpenedBy.IsUnset() { - vals = append(vals, "opened_by") - } if s.OrganizationID.IsValue() { vals = append(vals, "organization_id") } @@ -198,12 +132,6 @@ func (s CommunicationSetter) SetColumns() []string { if !s.ResponseTextLogID.IsUnset() { vals = append(vals, "response_text_log_id") } - if !s.SetPending.IsUnset() { - vals = append(vals, "set_pending") - } - if !s.SetPendingBy.IsUnset() { - vals = append(vals, "set_pending_by") - } if !s.SourceEmailLogID.IsUnset() { vals = append(vals, "source_email_log_id") } @@ -213,46 +141,19 @@ func (s CommunicationSetter) SetColumns() []string { if !s.SourceTextLogID.IsUnset() { vals = append(vals, "source_text_log_id") } - if !s.SetPossibleIssue.IsUnset() { - vals = append(vals, "set_possible_issue") - } - if !s.SetPossibleIssueBy.IsUnset() { - vals = append(vals, "set_possible_issue_by") - } - if !s.SetPossibleResolved.IsUnset() { - vals = append(vals, "set_possible_resolved") - } - if !s.SetPossibleResolvedBy.IsUnset() { - vals = append(vals, "set_possible_resolved_by") + if s.Status.IsValue() { + vals = append(vals, "status") } return vals } func (s CommunicationSetter) Overwrite(t *Communication) { - if !s.Closed.IsUnset() { - t.Closed = s.Closed.MustGetNull() - } - if !s.ClosedBy.IsUnset() { - t.ClosedBy = s.ClosedBy.MustGetNull() - } if s.Created.IsValue() { t.Created = s.Created.MustGet() } if s.ID.IsValue() { t.ID = s.ID.MustGet() } - if !s.Invalidated.IsUnset() { - t.Invalidated = s.Invalidated.MustGetNull() - } - if !s.InvalidatedBy.IsUnset() { - t.InvalidatedBy = s.InvalidatedBy.MustGetNull() - } - if !s.Opened.IsUnset() { - t.Opened = s.Opened.MustGetNull() - } - if !s.OpenedBy.IsUnset() { - t.OpenedBy = s.OpenedBy.MustGetNull() - } if s.OrganizationID.IsValue() { t.OrganizationID = s.OrganizationID.MustGet() } @@ -262,12 +163,6 @@ func (s CommunicationSetter) Overwrite(t *Communication) { if !s.ResponseTextLogID.IsUnset() { t.ResponseTextLogID = s.ResponseTextLogID.MustGetNull() } - if !s.SetPending.IsUnset() { - t.SetPending = s.SetPending.MustGetNull() - } - if !s.SetPendingBy.IsUnset() { - t.SetPendingBy = s.SetPendingBy.MustGetNull() - } if !s.SourceEmailLogID.IsUnset() { t.SourceEmailLogID = s.SourceEmailLogID.MustGetNull() } @@ -277,17 +172,8 @@ func (s CommunicationSetter) Overwrite(t *Communication) { if !s.SourceTextLogID.IsUnset() { t.SourceTextLogID = s.SourceTextLogID.MustGetNull() } - if !s.SetPossibleIssue.IsUnset() { - t.SetPossibleIssue = s.SetPossibleIssue.MustGetNull() - } - if !s.SetPossibleIssueBy.IsUnset() { - t.SetPossibleIssueBy = s.SetPossibleIssueBy.MustGetNull() - } - if !s.SetPossibleResolved.IsUnset() { - t.SetPossibleResolved = s.SetPossibleResolved.MustGetNull() - } - if !s.SetPossibleResolvedBy.IsUnset() { - t.SetPossibleResolvedBy = s.SetPossibleResolvedBy.MustGetNull() + if s.Status.IsValue() { + t.Status = s.Status.MustGet() } } @@ -297,127 +183,61 @@ func (s *CommunicationSetter) Apply(q *dialect.InsertQuery) { }) q.AppendValues(bob.ExpressionFunc(func(ctx context.Context, w io.StringWriter, d bob.Dialect, start int) ([]any, error) { - vals := make([]bob.Expression, 20) - if !s.Closed.IsUnset() { - vals[0] = psql.Arg(s.Closed.MustGetNull()) + vals := make([]bob.Expression, 9) + if s.Created.IsValue() { + vals[0] = psql.Arg(s.Created.MustGet()) } else { vals[0] = psql.Raw("DEFAULT") } - if !s.ClosedBy.IsUnset() { - vals[1] = psql.Arg(s.ClosedBy.MustGetNull()) + if s.ID.IsValue() { + vals[1] = psql.Arg(s.ID.MustGet()) } else { vals[1] = psql.Raw("DEFAULT") } - if s.Created.IsValue() { - vals[2] = psql.Arg(s.Created.MustGet()) + if s.OrganizationID.IsValue() { + vals[2] = psql.Arg(s.OrganizationID.MustGet()) } else { vals[2] = psql.Raw("DEFAULT") } - if s.ID.IsValue() { - vals[3] = psql.Arg(s.ID.MustGet()) + if !s.ResponseEmailLogID.IsUnset() { + vals[3] = psql.Arg(s.ResponseEmailLogID.MustGetNull()) } else { vals[3] = psql.Raw("DEFAULT") } - if !s.Invalidated.IsUnset() { - vals[4] = psql.Arg(s.Invalidated.MustGetNull()) + if !s.ResponseTextLogID.IsUnset() { + vals[4] = psql.Arg(s.ResponseTextLogID.MustGetNull()) } else { vals[4] = psql.Raw("DEFAULT") } - if !s.InvalidatedBy.IsUnset() { - vals[5] = psql.Arg(s.InvalidatedBy.MustGetNull()) + if !s.SourceEmailLogID.IsUnset() { + vals[5] = psql.Arg(s.SourceEmailLogID.MustGetNull()) } else { vals[5] = psql.Raw("DEFAULT") } - if !s.Opened.IsUnset() { - vals[6] = psql.Arg(s.Opened.MustGetNull()) + if !s.SourceReportID.IsUnset() { + vals[6] = psql.Arg(s.SourceReportID.MustGetNull()) } else { vals[6] = psql.Raw("DEFAULT") } - if !s.OpenedBy.IsUnset() { - vals[7] = psql.Arg(s.OpenedBy.MustGetNull()) + if !s.SourceTextLogID.IsUnset() { + vals[7] = psql.Arg(s.SourceTextLogID.MustGetNull()) } else { vals[7] = psql.Raw("DEFAULT") } - if s.OrganizationID.IsValue() { - vals[8] = psql.Arg(s.OrganizationID.MustGet()) + if s.Status.IsValue() { + vals[8] = psql.Arg(s.Status.MustGet()) } else { vals[8] = psql.Raw("DEFAULT") } - if !s.ResponseEmailLogID.IsUnset() { - vals[9] = psql.Arg(s.ResponseEmailLogID.MustGetNull()) - } else { - vals[9] = psql.Raw("DEFAULT") - } - - if !s.ResponseTextLogID.IsUnset() { - vals[10] = psql.Arg(s.ResponseTextLogID.MustGetNull()) - } else { - vals[10] = psql.Raw("DEFAULT") - } - - if !s.SetPending.IsUnset() { - vals[11] = psql.Arg(s.SetPending.MustGetNull()) - } else { - vals[11] = psql.Raw("DEFAULT") - } - - if !s.SetPendingBy.IsUnset() { - vals[12] = psql.Arg(s.SetPendingBy.MustGetNull()) - } else { - vals[12] = psql.Raw("DEFAULT") - } - - if !s.SourceEmailLogID.IsUnset() { - vals[13] = psql.Arg(s.SourceEmailLogID.MustGetNull()) - } else { - vals[13] = psql.Raw("DEFAULT") - } - - if !s.SourceReportID.IsUnset() { - vals[14] = psql.Arg(s.SourceReportID.MustGetNull()) - } else { - vals[14] = psql.Raw("DEFAULT") - } - - if !s.SourceTextLogID.IsUnset() { - vals[15] = psql.Arg(s.SourceTextLogID.MustGetNull()) - } else { - vals[15] = psql.Raw("DEFAULT") - } - - if !s.SetPossibleIssue.IsUnset() { - vals[16] = psql.Arg(s.SetPossibleIssue.MustGetNull()) - } else { - vals[16] = psql.Raw("DEFAULT") - } - - if !s.SetPossibleIssueBy.IsUnset() { - vals[17] = psql.Arg(s.SetPossibleIssueBy.MustGetNull()) - } else { - vals[17] = psql.Raw("DEFAULT") - } - - if !s.SetPossibleResolved.IsUnset() { - vals[18] = psql.Arg(s.SetPossibleResolved.MustGetNull()) - } else { - vals[18] = psql.Raw("DEFAULT") - } - - if !s.SetPossibleResolvedBy.IsUnset() { - vals[19] = psql.Arg(s.SetPossibleResolvedBy.MustGetNull()) - } else { - vals[19] = psql.Raw("DEFAULT") - } - return bob.ExpressSlice(ctx, w, d, start, vals, "", ", ", "") })) } @@ -427,21 +247,7 @@ func (s CommunicationSetter) UpdateMod() bob.Mod[*dialect.UpdateQuery] { } func (s CommunicationSetter) Expressions(prefix ...string) []bob.Expression { - exprs := make([]bob.Expression, 0, 20) - - if !s.Closed.IsUnset() { - exprs = append(exprs, expr.Join{Sep: " = ", Exprs: []bob.Expression{ - psql.Quote(append(prefix, "closed")...), - psql.Arg(s.Closed), - }}) - } - - if !s.ClosedBy.IsUnset() { - exprs = append(exprs, expr.Join{Sep: " = ", Exprs: []bob.Expression{ - psql.Quote(append(prefix, "closed_by")...), - psql.Arg(s.ClosedBy), - }}) - } + exprs := make([]bob.Expression, 0, 9) if s.Created.IsValue() { exprs = append(exprs, expr.Join{Sep: " = ", Exprs: []bob.Expression{ @@ -457,34 +263,6 @@ func (s CommunicationSetter) Expressions(prefix ...string) []bob.Expression { }}) } - if !s.Invalidated.IsUnset() { - exprs = append(exprs, expr.Join{Sep: " = ", Exprs: []bob.Expression{ - psql.Quote(append(prefix, "invalidated")...), - psql.Arg(s.Invalidated), - }}) - } - - if !s.InvalidatedBy.IsUnset() { - exprs = append(exprs, expr.Join{Sep: " = ", Exprs: []bob.Expression{ - psql.Quote(append(prefix, "invalidated_by")...), - psql.Arg(s.InvalidatedBy), - }}) - } - - if !s.Opened.IsUnset() { - exprs = append(exprs, expr.Join{Sep: " = ", Exprs: []bob.Expression{ - psql.Quote(append(prefix, "opened")...), - psql.Arg(s.Opened), - }}) - } - - if !s.OpenedBy.IsUnset() { - exprs = append(exprs, expr.Join{Sep: " = ", Exprs: []bob.Expression{ - psql.Quote(append(prefix, "opened_by")...), - psql.Arg(s.OpenedBy), - }}) - } - if s.OrganizationID.IsValue() { exprs = append(exprs, expr.Join{Sep: " = ", Exprs: []bob.Expression{ psql.Quote(append(prefix, "organization_id")...), @@ -506,20 +284,6 @@ func (s CommunicationSetter) Expressions(prefix ...string) []bob.Expression { }}) } - if !s.SetPending.IsUnset() { - exprs = append(exprs, expr.Join{Sep: " = ", Exprs: []bob.Expression{ - psql.Quote(append(prefix, "set_pending")...), - psql.Arg(s.SetPending), - }}) - } - - if !s.SetPendingBy.IsUnset() { - exprs = append(exprs, expr.Join{Sep: " = ", Exprs: []bob.Expression{ - psql.Quote(append(prefix, "set_pending_by")...), - psql.Arg(s.SetPendingBy), - }}) - } - if !s.SourceEmailLogID.IsUnset() { exprs = append(exprs, expr.Join{Sep: " = ", Exprs: []bob.Expression{ psql.Quote(append(prefix, "source_email_log_id")...), @@ -541,31 +305,10 @@ func (s CommunicationSetter) Expressions(prefix ...string) []bob.Expression { }}) } - if !s.SetPossibleIssue.IsUnset() { + if s.Status.IsValue() { exprs = append(exprs, expr.Join{Sep: " = ", Exprs: []bob.Expression{ - psql.Quote(append(prefix, "set_possible_issue")...), - psql.Arg(s.SetPossibleIssue), - }}) - } - - if !s.SetPossibleIssueBy.IsUnset() { - exprs = append(exprs, expr.Join{Sep: " = ", Exprs: []bob.Expression{ - psql.Quote(append(prefix, "set_possible_issue_by")...), - psql.Arg(s.SetPossibleIssueBy), - }}) - } - - if !s.SetPossibleResolved.IsUnset() { - exprs = append(exprs, expr.Join{Sep: " = ", Exprs: []bob.Expression{ - psql.Quote(append(prefix, "set_possible_resolved")...), - psql.Arg(s.SetPossibleResolved), - }}) - } - - if !s.SetPossibleResolvedBy.IsUnset() { - exprs = append(exprs, expr.Join{Sep: " = ", Exprs: []bob.Expression{ - psql.Quote(append(prefix, "set_possible_resolved_by")...), - psql.Arg(s.SetPossibleResolvedBy), + psql.Quote(append(prefix, "status")...), + psql.Arg(s.Status), }}) } @@ -795,78 +538,6 @@ func (o CommunicationSlice) ReloadAll(ctx context.Context, exec bob.Executor) er return nil } -// ClosedByUser starts a query for related objects on user_ -func (o *Communication) ClosedByUser(mods ...bob.Mod[*dialect.SelectQuery]) UsersQuery { - return Users.Query(append(mods, - sm.Where(Users.Columns.ID.EQ(psql.Arg(o.ClosedBy))), - )...) -} - -func (os CommunicationSlice) ClosedByUser(mods ...bob.Mod[*dialect.SelectQuery]) UsersQuery { - pkClosedBy := make(pgtypes.Array[null.Val[int32]], 0, len(os)) - for _, o := range os { - if o == nil { - continue - } - pkClosedBy = append(pkClosedBy, o.ClosedBy) - } - PKArgExpr := psql.Select(sm.Columns( - psql.F("unnest", psql.Cast(psql.Arg(pkClosedBy), "integer[]")), - )) - - return Users.Query(append(mods, - sm.Where(psql.Group(Users.Columns.ID).OP("IN", PKArgExpr)), - )...) -} - -// InvalidatedByUser starts a query for related objects on user_ -func (o *Communication) InvalidatedByUser(mods ...bob.Mod[*dialect.SelectQuery]) UsersQuery { - return Users.Query(append(mods, - sm.Where(Users.Columns.ID.EQ(psql.Arg(o.InvalidatedBy))), - )...) -} - -func (os CommunicationSlice) InvalidatedByUser(mods ...bob.Mod[*dialect.SelectQuery]) UsersQuery { - pkInvalidatedBy := make(pgtypes.Array[null.Val[int32]], 0, len(os)) - for _, o := range os { - if o == nil { - continue - } - pkInvalidatedBy = append(pkInvalidatedBy, o.InvalidatedBy) - } - PKArgExpr := psql.Select(sm.Columns( - psql.F("unnest", psql.Cast(psql.Arg(pkInvalidatedBy), "integer[]")), - )) - - return Users.Query(append(mods, - sm.Where(psql.Group(Users.Columns.ID).OP("IN", PKArgExpr)), - )...) -} - -// OpenedByUser starts a query for related objects on user_ -func (o *Communication) OpenedByUser(mods ...bob.Mod[*dialect.SelectQuery]) UsersQuery { - return Users.Query(append(mods, - sm.Where(Users.Columns.ID.EQ(psql.Arg(o.OpenedBy))), - )...) -} - -func (os CommunicationSlice) OpenedByUser(mods ...bob.Mod[*dialect.SelectQuery]) UsersQuery { - pkOpenedBy := make(pgtypes.Array[null.Val[int32]], 0, len(os)) - for _, o := range os { - if o == nil { - continue - } - pkOpenedBy = append(pkOpenedBy, o.OpenedBy) - } - PKArgExpr := psql.Select(sm.Columns( - psql.F("unnest", psql.Cast(psql.Arg(pkOpenedBy), "integer[]")), - )) - - return Users.Query(append(mods, - sm.Where(psql.Group(Users.Columns.ID).OP("IN", PKArgExpr)), - )...) -} - // Organization starts a query for related objects on organization func (o *Communication) Organization(mods ...bob.Mod[*dialect.SelectQuery]) OrganizationsQuery { return Organizations.Query(append(mods, @@ -939,78 +610,6 @@ func (os CommunicationSlice) ResponseTextLogTextLog(mods ...bob.Mod[*dialect.Sel )...) } -// SetPendingByUser starts a query for related objects on user_ -func (o *Communication) SetPendingByUser(mods ...bob.Mod[*dialect.SelectQuery]) UsersQuery { - return Users.Query(append(mods, - sm.Where(Users.Columns.ID.EQ(psql.Arg(o.SetPendingBy))), - )...) -} - -func (os CommunicationSlice) SetPendingByUser(mods ...bob.Mod[*dialect.SelectQuery]) UsersQuery { - pkSetPendingBy := make(pgtypes.Array[null.Val[int32]], 0, len(os)) - for _, o := range os { - if o == nil { - continue - } - pkSetPendingBy = append(pkSetPendingBy, o.SetPendingBy) - } - PKArgExpr := psql.Select(sm.Columns( - psql.F("unnest", psql.Cast(psql.Arg(pkSetPendingBy), "integer[]")), - )) - - return Users.Query(append(mods, - sm.Where(psql.Group(Users.Columns.ID).OP("IN", PKArgExpr)), - )...) -} - -// SetPossibleIssueByUser starts a query for related objects on user_ -func (o *Communication) SetPossibleIssueByUser(mods ...bob.Mod[*dialect.SelectQuery]) UsersQuery { - return Users.Query(append(mods, - sm.Where(Users.Columns.ID.EQ(psql.Arg(o.SetPossibleIssueBy))), - )...) -} - -func (os CommunicationSlice) SetPossibleIssueByUser(mods ...bob.Mod[*dialect.SelectQuery]) UsersQuery { - pkSetPossibleIssueBy := make(pgtypes.Array[null.Val[int32]], 0, len(os)) - for _, o := range os { - if o == nil { - continue - } - pkSetPossibleIssueBy = append(pkSetPossibleIssueBy, o.SetPossibleIssueBy) - } - PKArgExpr := psql.Select(sm.Columns( - psql.F("unnest", psql.Cast(psql.Arg(pkSetPossibleIssueBy), "integer[]")), - )) - - return Users.Query(append(mods, - sm.Where(psql.Group(Users.Columns.ID).OP("IN", PKArgExpr)), - )...) -} - -// SetPossibleResolvedByUser starts a query for related objects on user_ -func (o *Communication) SetPossibleResolvedByUser(mods ...bob.Mod[*dialect.SelectQuery]) UsersQuery { - return Users.Query(append(mods, - sm.Where(Users.Columns.ID.EQ(psql.Arg(o.SetPossibleResolvedBy))), - )...) -} - -func (os CommunicationSlice) SetPossibleResolvedByUser(mods ...bob.Mod[*dialect.SelectQuery]) UsersQuery { - pkSetPossibleResolvedBy := make(pgtypes.Array[null.Val[int32]], 0, len(os)) - for _, o := range os { - if o == nil { - continue - } - pkSetPossibleResolvedBy = append(pkSetPossibleResolvedBy, o.SetPossibleResolvedBy) - } - PKArgExpr := psql.Select(sm.Columns( - psql.F("unnest", psql.Cast(psql.Arg(pkSetPossibleResolvedBy), "integer[]")), - )) - - return Users.Query(append(mods, - sm.Where(psql.Group(Users.Columns.ID).OP("IN", PKArgExpr)), - )...) -} - // SourceEmailLogEmailLog starts a query for related objects on comms.email_log func (o *Communication) SourceEmailLogEmailLog(mods ...bob.Mod[*dialect.SelectQuery]) CommsEmailLogsQuery { return CommsEmailLogs.Query(append(mods, @@ -1083,148 +682,28 @@ func (os CommunicationSlice) SourceTextLogTextLog(mods ...bob.Mod[*dialect.Selec )...) } -func attachCommunicationClosedByUser0(ctx context.Context, exec bob.Executor, count int, communication0 *Communication, user1 *User) (*Communication, error) { - setter := &CommunicationSetter{ - ClosedBy: omitnull.From(user1.ID), - } - - err := communication0.Update(ctx, exec, setter) - if err != nil { - return nil, fmt.Errorf("attachCommunicationClosedByUser0: %w", err) - } - - return communication0, nil +// CommunicationLogEntries starts a query for related objects on communication_log_entry +func (o *Communication) CommunicationLogEntries(mods ...bob.Mod[*dialect.SelectQuery]) CommunicationLogEntriesQuery { + return CommunicationLogEntries.Query(append(mods, + sm.Where(CommunicationLogEntries.Columns.CommunicationID.EQ(psql.Arg(o.ID))), + )...) } -func (communication0 *Communication) InsertClosedByUser(ctx context.Context, exec bob.Executor, related *UserSetter) error { - var err error - - user1, err := Users.Insert(related).One(ctx, exec) - if err != nil { - return fmt.Errorf("inserting related objects: %w", err) +func (os CommunicationSlice) CommunicationLogEntries(mods ...bob.Mod[*dialect.SelectQuery]) CommunicationLogEntriesQuery { + 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[]")), + )) - _, err = attachCommunicationClosedByUser0(ctx, exec, 1, communication0, user1) - if err != nil { - return err - } - - communication0.R.ClosedByUser = user1 - - user1.R.ClosedByCommunications = append(user1.R.ClosedByCommunications, communication0) - - return nil -} - -func (communication0 *Communication) AttachClosedByUser(ctx context.Context, exec bob.Executor, user1 *User) error { - var err error - - _, err = attachCommunicationClosedByUser0(ctx, exec, 1, communication0, user1) - if err != nil { - return err - } - - communication0.R.ClosedByUser = user1 - - user1.R.ClosedByCommunications = append(user1.R.ClosedByCommunications, communication0) - - return nil -} - -func attachCommunicationInvalidatedByUser0(ctx context.Context, exec bob.Executor, count int, communication0 *Communication, user1 *User) (*Communication, error) { - setter := &CommunicationSetter{ - InvalidatedBy: omitnull.From(user1.ID), - } - - err := communication0.Update(ctx, exec, setter) - if err != nil { - return nil, fmt.Errorf("attachCommunicationInvalidatedByUser0: %w", err) - } - - return communication0, nil -} - -func (communication0 *Communication) InsertInvalidatedByUser(ctx context.Context, exec bob.Executor, related *UserSetter) error { - var err error - - user1, err := Users.Insert(related).One(ctx, exec) - if err != nil { - return fmt.Errorf("inserting related objects: %w", err) - } - - _, err = attachCommunicationInvalidatedByUser0(ctx, exec, 1, communication0, user1) - if err != nil { - return err - } - - communication0.R.InvalidatedByUser = user1 - - user1.R.InvalidatedByCommunications = append(user1.R.InvalidatedByCommunications, communication0) - - return nil -} - -func (communication0 *Communication) AttachInvalidatedByUser(ctx context.Context, exec bob.Executor, user1 *User) error { - var err error - - _, err = attachCommunicationInvalidatedByUser0(ctx, exec, 1, communication0, user1) - if err != nil { - return err - } - - communication0.R.InvalidatedByUser = user1 - - user1.R.InvalidatedByCommunications = append(user1.R.InvalidatedByCommunications, communication0) - - return nil -} - -func attachCommunicationOpenedByUser0(ctx context.Context, exec bob.Executor, count int, communication0 *Communication, user1 *User) (*Communication, error) { - setter := &CommunicationSetter{ - OpenedBy: omitnull.From(user1.ID), - } - - err := communication0.Update(ctx, exec, setter) - if err != nil { - return nil, fmt.Errorf("attachCommunicationOpenedByUser0: %w", err) - } - - return communication0, nil -} - -func (communication0 *Communication) InsertOpenedByUser(ctx context.Context, exec bob.Executor, related *UserSetter) error { - var err error - - user1, err := Users.Insert(related).One(ctx, exec) - if err != nil { - return fmt.Errorf("inserting related objects: %w", err) - } - - _, err = attachCommunicationOpenedByUser0(ctx, exec, 1, communication0, user1) - if err != nil { - return err - } - - communication0.R.OpenedByUser = user1 - - user1.R.OpenedByCommunications = append(user1.R.OpenedByCommunications, communication0) - - return nil -} - -func (communication0 *Communication) AttachOpenedByUser(ctx context.Context, exec bob.Executor, user1 *User) error { - var err error - - _, err = attachCommunicationOpenedByUser0(ctx, exec, 1, communication0, user1) - if err != nil { - return err - } - - communication0.R.OpenedByUser = user1 - - user1.R.OpenedByCommunications = append(user1.R.OpenedByCommunications, communication0) - - return nil + return CommunicationLogEntries.Query(append(mods, + sm.Where(psql.Group(CommunicationLogEntries.Columns.CommunicationID).OP("IN", PKArgExpr)), + )...) } func attachCommunicationOrganization0(ctx context.Context, exec bob.Executor, count int, communication0 *Communication, organization1 *Organization) (*Communication, error) { @@ -1371,150 +850,6 @@ func (communication0 *Communication) AttachResponseTextLogTextLog(ctx context.Co return nil } -func attachCommunicationSetPendingByUser0(ctx context.Context, exec bob.Executor, count int, communication0 *Communication, user1 *User) (*Communication, error) { - setter := &CommunicationSetter{ - SetPendingBy: omitnull.From(user1.ID), - } - - err := communication0.Update(ctx, exec, setter) - if err != nil { - return nil, fmt.Errorf("attachCommunicationSetPendingByUser0: %w", err) - } - - return communication0, nil -} - -func (communication0 *Communication) InsertSetPendingByUser(ctx context.Context, exec bob.Executor, related *UserSetter) error { - var err error - - user1, err := Users.Insert(related).One(ctx, exec) - if err != nil { - return fmt.Errorf("inserting related objects: %w", err) - } - - _, err = attachCommunicationSetPendingByUser0(ctx, exec, 1, communication0, user1) - if err != nil { - return err - } - - communication0.R.SetPendingByUser = user1 - - user1.R.SetPendingByCommunications = append(user1.R.SetPendingByCommunications, communication0) - - return nil -} - -func (communication0 *Communication) AttachSetPendingByUser(ctx context.Context, exec bob.Executor, user1 *User) error { - var err error - - _, err = attachCommunicationSetPendingByUser0(ctx, exec, 1, communication0, user1) - if err != nil { - return err - } - - communication0.R.SetPendingByUser = user1 - - user1.R.SetPendingByCommunications = append(user1.R.SetPendingByCommunications, communication0) - - return nil -} - -func attachCommunicationSetPossibleIssueByUser0(ctx context.Context, exec bob.Executor, count int, communication0 *Communication, user1 *User) (*Communication, error) { - setter := &CommunicationSetter{ - SetPossibleIssueBy: omitnull.From(user1.ID), - } - - err := communication0.Update(ctx, exec, setter) - if err != nil { - return nil, fmt.Errorf("attachCommunicationSetPossibleIssueByUser0: %w", err) - } - - return communication0, nil -} - -func (communication0 *Communication) InsertSetPossibleIssueByUser(ctx context.Context, exec bob.Executor, related *UserSetter) error { - var err error - - user1, err := Users.Insert(related).One(ctx, exec) - if err != nil { - return fmt.Errorf("inserting related objects: %w", err) - } - - _, err = attachCommunicationSetPossibleIssueByUser0(ctx, exec, 1, communication0, user1) - if err != nil { - return err - } - - communication0.R.SetPossibleIssueByUser = user1 - - user1.R.SetPossibleIssueByCommunications = append(user1.R.SetPossibleIssueByCommunications, communication0) - - return nil -} - -func (communication0 *Communication) AttachSetPossibleIssueByUser(ctx context.Context, exec bob.Executor, user1 *User) error { - var err error - - _, err = attachCommunicationSetPossibleIssueByUser0(ctx, exec, 1, communication0, user1) - if err != nil { - return err - } - - communication0.R.SetPossibleIssueByUser = user1 - - user1.R.SetPossibleIssueByCommunications = append(user1.R.SetPossibleIssueByCommunications, communication0) - - return nil -} - -func attachCommunicationSetPossibleResolvedByUser0(ctx context.Context, exec bob.Executor, count int, communication0 *Communication, user1 *User) (*Communication, error) { - setter := &CommunicationSetter{ - SetPossibleResolvedBy: omitnull.From(user1.ID), - } - - err := communication0.Update(ctx, exec, setter) - if err != nil { - return nil, fmt.Errorf("attachCommunicationSetPossibleResolvedByUser0: %w", err) - } - - return communication0, nil -} - -func (communication0 *Communication) InsertSetPossibleResolvedByUser(ctx context.Context, exec bob.Executor, related *UserSetter) error { - var err error - - user1, err := Users.Insert(related).One(ctx, exec) - if err != nil { - return fmt.Errorf("inserting related objects: %w", err) - } - - _, err = attachCommunicationSetPossibleResolvedByUser0(ctx, exec, 1, communication0, user1) - if err != nil { - return err - } - - communication0.R.SetPossibleResolvedByUser = user1 - - user1.R.SetPossibleResolvedByCommunications = append(user1.R.SetPossibleResolvedByCommunications, communication0) - - return nil -} - -func (communication0 *Communication) AttachSetPossibleResolvedByUser(ctx context.Context, exec bob.Executor, user1 *User) error { - var err error - - _, err = attachCommunicationSetPossibleResolvedByUser0(ctx, exec, 1, communication0, user1) - if err != nil { - return err - } - - communication0.R.SetPossibleResolvedByUser = user1 - - user1.R.SetPossibleResolvedByCommunications = append(user1.R.SetPossibleResolvedByCommunications, communication0) - - return nil -} - func attachCommunicationSourceEmailLogEmailLog0(ctx context.Context, exec bob.Executor, count int, communication0 *Communication, commsEmailLog1 *CommsEmailLog) (*Communication, error) { setter := &CommunicationSetter{ SourceEmailLogID: omitnull.From(commsEmailLog1.ID), @@ -1659,27 +994,84 @@ func (communication0 *Communication) AttachSourceTextLogTextLog(ctx context.Cont return nil } +func insertCommunicationCommunicationLogEntries0(ctx context.Context, exec bob.Executor, communicationLogEntries1 []*CommunicationLogEntrySetter, communication0 *Communication) (CommunicationLogEntrySlice, error) { + for i := range communicationLogEntries1 { + communicationLogEntries1[i].CommunicationID = omit.From(communication0.ID) + } + + ret, err := CommunicationLogEntries.Insert(bob.ToMods(communicationLogEntries1...)).All(ctx, exec) + if err != nil { + return ret, fmt.Errorf("insertCommunicationCommunicationLogEntries0: %w", err) + } + + return ret, nil +} + +func attachCommunicationCommunicationLogEntries0(ctx context.Context, exec bob.Executor, count int, communicationLogEntries1 CommunicationLogEntrySlice, communication0 *Communication) (CommunicationLogEntrySlice, error) { + setter := &CommunicationLogEntrySetter{ + CommunicationID: omit.From(communication0.ID), + } + + err := communicationLogEntries1.UpdateAll(ctx, exec, *setter) + if err != nil { + return nil, fmt.Errorf("attachCommunicationCommunicationLogEntries0: %w", err) + } + + return communicationLogEntries1, nil +} + +func (communication0 *Communication) InsertCommunicationLogEntries(ctx context.Context, exec bob.Executor, related ...*CommunicationLogEntrySetter) error { + if len(related) == 0 { + return nil + } + + var err error + + communicationLogEntries1, err := insertCommunicationCommunicationLogEntries0(ctx, exec, related, communication0) + if err != nil { + return err + } + + communication0.R.CommunicationLogEntries = append(communication0.R.CommunicationLogEntries, communicationLogEntries1...) + + for _, rel := range communicationLogEntries1 { + rel.R.Communication = communication0 + } + return nil +} + +func (communication0 *Communication) AttachCommunicationLogEntries(ctx context.Context, exec bob.Executor, related ...*CommunicationLogEntry) error { + if len(related) == 0 { + return nil + } + + var err error + communicationLogEntries1 := CommunicationLogEntrySlice(related) + + _, err = attachCommunicationCommunicationLogEntries0(ctx, exec, len(related), communicationLogEntries1, communication0) + if err != nil { + return err + } + + communication0.R.CommunicationLogEntries = append(communication0.R.CommunicationLogEntries, communicationLogEntries1...) + + for _, rel := range related { + rel.R.Communication = communication0 + } + + return nil +} + type communicationWhere[Q psql.Filterable] struct { - Closed psql.WhereNullMod[Q, time.Time] - ClosedBy psql.WhereNullMod[Q, int32] - Created psql.WhereMod[Q, time.Time] - ID psql.WhereMod[Q, int32] - Invalidated psql.WhereNullMod[Q, time.Time] - InvalidatedBy psql.WhereNullMod[Q, int32] - Opened psql.WhereNullMod[Q, time.Time] - OpenedBy psql.WhereNullMod[Q, int32] - OrganizationID psql.WhereMod[Q, int32] - ResponseEmailLogID psql.WhereNullMod[Q, int32] - ResponseTextLogID psql.WhereNullMod[Q, int32] - SetPending psql.WhereNullMod[Q, time.Time] - SetPendingBy psql.WhereNullMod[Q, int32] - SourceEmailLogID psql.WhereNullMod[Q, int32] - SourceReportID psql.WhereNullMod[Q, int32] - SourceTextLogID psql.WhereNullMod[Q, int32] - SetPossibleIssue psql.WhereNullMod[Q, time.Time] - SetPossibleIssueBy psql.WhereNullMod[Q, int32] - SetPossibleResolved psql.WhereNullMod[Q, time.Time] - SetPossibleResolvedBy psql.WhereNullMod[Q, int32] + Created psql.WhereMod[Q, time.Time] + ID psql.WhereMod[Q, int32] + OrganizationID psql.WhereMod[Q, int32] + ResponseEmailLogID psql.WhereNullMod[Q, int32] + ResponseTextLogID psql.WhereNullMod[Q, int32] + SourceEmailLogID psql.WhereNullMod[Q, int32] + SourceReportID psql.WhereNullMod[Q, int32] + SourceTextLogID psql.WhereNullMod[Q, int32] + Status psql.WhereMod[Q, enums.Communicationstatus] } func (communicationWhere[Q]) AliasedAs(alias string) communicationWhere[Q] { @@ -1688,26 +1080,15 @@ func (communicationWhere[Q]) AliasedAs(alias string) communicationWhere[Q] { func buildCommunicationWhere[Q psql.Filterable](cols communicationColumns) communicationWhere[Q] { return communicationWhere[Q]{ - Closed: psql.WhereNull[Q, time.Time](cols.Closed), - ClosedBy: psql.WhereNull[Q, int32](cols.ClosedBy), - Created: psql.Where[Q, time.Time](cols.Created), - ID: psql.Where[Q, int32](cols.ID), - Invalidated: psql.WhereNull[Q, time.Time](cols.Invalidated), - InvalidatedBy: psql.WhereNull[Q, int32](cols.InvalidatedBy), - Opened: psql.WhereNull[Q, time.Time](cols.Opened), - OpenedBy: psql.WhereNull[Q, int32](cols.OpenedBy), - OrganizationID: psql.Where[Q, int32](cols.OrganizationID), - ResponseEmailLogID: psql.WhereNull[Q, int32](cols.ResponseEmailLogID), - ResponseTextLogID: psql.WhereNull[Q, int32](cols.ResponseTextLogID), - SetPending: psql.WhereNull[Q, time.Time](cols.SetPending), - SetPendingBy: psql.WhereNull[Q, int32](cols.SetPendingBy), - SourceEmailLogID: psql.WhereNull[Q, int32](cols.SourceEmailLogID), - SourceReportID: psql.WhereNull[Q, int32](cols.SourceReportID), - SourceTextLogID: psql.WhereNull[Q, int32](cols.SourceTextLogID), - SetPossibleIssue: psql.WhereNull[Q, time.Time](cols.SetPossibleIssue), - SetPossibleIssueBy: psql.WhereNull[Q, int32](cols.SetPossibleIssueBy), - SetPossibleResolved: psql.WhereNull[Q, time.Time](cols.SetPossibleResolved), - SetPossibleResolvedBy: psql.WhereNull[Q, int32](cols.SetPossibleResolvedBy), + Created: psql.Where[Q, time.Time](cols.Created), + ID: psql.Where[Q, int32](cols.ID), + OrganizationID: psql.Where[Q, int32](cols.OrganizationID), + ResponseEmailLogID: psql.WhereNull[Q, int32](cols.ResponseEmailLogID), + ResponseTextLogID: psql.WhereNull[Q, int32](cols.ResponseTextLogID), + SourceEmailLogID: psql.WhereNull[Q, int32](cols.SourceEmailLogID), + SourceReportID: psql.WhereNull[Q, int32](cols.SourceReportID), + SourceTextLogID: psql.WhereNull[Q, int32](cols.SourceTextLogID), + Status: psql.Where[Q, enums.Communicationstatus](cols.Status), } } @@ -1717,42 +1098,6 @@ func (o *Communication) Preload(name string, retrieved any) error { } switch name { - case "ClosedByUser": - rel, ok := retrieved.(*User) - if !ok { - return fmt.Errorf("communication cannot load %T as %q", retrieved, name) - } - - o.R.ClosedByUser = rel - - if rel != nil { - rel.R.ClosedByCommunications = CommunicationSlice{o} - } - return nil - case "InvalidatedByUser": - rel, ok := retrieved.(*User) - if !ok { - return fmt.Errorf("communication cannot load %T as %q", retrieved, name) - } - - o.R.InvalidatedByUser = rel - - if rel != nil { - rel.R.InvalidatedByCommunications = CommunicationSlice{o} - } - return nil - case "OpenedByUser": - rel, ok := retrieved.(*User) - if !ok { - return fmt.Errorf("communication cannot load %T as %q", retrieved, name) - } - - o.R.OpenedByUser = rel - - if rel != nil { - rel.R.OpenedByCommunications = CommunicationSlice{o} - } - return nil case "Organization": rel, ok := retrieved.(*Organization) if !ok { @@ -1789,42 +1134,6 @@ func (o *Communication) Preload(name string, retrieved any) error { rel.R.ResponseTextLogCommunications = CommunicationSlice{o} } return nil - case "SetPendingByUser": - rel, ok := retrieved.(*User) - if !ok { - return fmt.Errorf("communication cannot load %T as %q", retrieved, name) - } - - o.R.SetPendingByUser = rel - - if rel != nil { - rel.R.SetPendingByCommunications = CommunicationSlice{o} - } - return nil - case "SetPossibleIssueByUser": - rel, ok := retrieved.(*User) - if !ok { - return fmt.Errorf("communication cannot load %T as %q", retrieved, name) - } - - o.R.SetPossibleIssueByUser = rel - - if rel != nil { - rel.R.SetPossibleIssueByCommunications = CommunicationSlice{o} - } - return nil - case "SetPossibleResolvedByUser": - rel, ok := retrieved.(*User) - if !ok { - return fmt.Errorf("communication cannot load %T as %q", retrieved, name) - } - - o.R.SetPossibleResolvedByUser = rel - - if rel != nil { - rel.R.SetPossibleResolvedByCommunications = CommunicationSlice{o} - } - return nil case "SourceEmailLogEmailLog": rel, ok := retrieved.(*CommsEmailLog) if !ok { @@ -1861,67 +1170,36 @@ func (o *Communication) Preload(name string, retrieved any) error { rel.R.SourceTextLogCommunications = CommunicationSlice{o} } return nil + case "CommunicationLogEntries": + rels, ok := retrieved.(CommunicationLogEntrySlice) + if !ok { + return fmt.Errorf("communication cannot load %T as %q", retrieved, name) + } + + o.R.CommunicationLogEntries = rels + + for _, rel := range rels { + if rel != nil { + rel.R.Communication = o + } + } + return nil default: return fmt.Errorf("communication has no relationship %q", name) } } type communicationPreloader struct { - ClosedByUser func(...psql.PreloadOption) psql.Preloader - InvalidatedByUser func(...psql.PreloadOption) psql.Preloader - OpenedByUser func(...psql.PreloadOption) psql.Preloader - Organization func(...psql.PreloadOption) psql.Preloader - ResponseEmailLogEmailLog func(...psql.PreloadOption) psql.Preloader - ResponseTextLogTextLog func(...psql.PreloadOption) psql.Preloader - SetPendingByUser func(...psql.PreloadOption) psql.Preloader - SetPossibleIssueByUser func(...psql.PreloadOption) psql.Preloader - SetPossibleResolvedByUser func(...psql.PreloadOption) psql.Preloader - SourceEmailLogEmailLog func(...psql.PreloadOption) psql.Preloader - SourceReportReport func(...psql.PreloadOption) psql.Preloader - SourceTextLogTextLog func(...psql.PreloadOption) psql.Preloader + Organization func(...psql.PreloadOption) psql.Preloader + ResponseEmailLogEmailLog func(...psql.PreloadOption) psql.Preloader + ResponseTextLogTextLog func(...psql.PreloadOption) psql.Preloader + SourceEmailLogEmailLog func(...psql.PreloadOption) psql.Preloader + SourceReportReport func(...psql.PreloadOption) psql.Preloader + SourceTextLogTextLog func(...psql.PreloadOption) psql.Preloader } func buildCommunicationPreloader() communicationPreloader { return communicationPreloader{ - ClosedByUser: func(opts ...psql.PreloadOption) psql.Preloader { - return psql.Preload[*User, UserSlice](psql.PreloadRel{ - Name: "ClosedByUser", - Sides: []psql.PreloadSide{ - { - From: Communications, - To: Users, - FromColumns: []string{"closed_by"}, - ToColumns: []string{"id"}, - }, - }, - }, Users.Columns.Names(), opts...) - }, - InvalidatedByUser: func(opts ...psql.PreloadOption) psql.Preloader { - return psql.Preload[*User, UserSlice](psql.PreloadRel{ - Name: "InvalidatedByUser", - Sides: []psql.PreloadSide{ - { - From: Communications, - To: Users, - FromColumns: []string{"invalidated_by"}, - ToColumns: []string{"id"}, - }, - }, - }, Users.Columns.Names(), opts...) - }, - OpenedByUser: func(opts ...psql.PreloadOption) psql.Preloader { - return psql.Preload[*User, UserSlice](psql.PreloadRel{ - Name: "OpenedByUser", - Sides: []psql.PreloadSide{ - { - From: Communications, - To: Users, - FromColumns: []string{"opened_by"}, - ToColumns: []string{"id"}, - }, - }, - }, Users.Columns.Names(), opts...) - }, Organization: func(opts ...psql.PreloadOption) psql.Preloader { return psql.Preload[*Organization, OrganizationSlice](psql.PreloadRel{ Name: "Organization", @@ -1961,45 +1239,6 @@ func buildCommunicationPreloader() communicationPreloader { }, }, CommsTextLogs.Columns.Names(), opts...) }, - SetPendingByUser: func(opts ...psql.PreloadOption) psql.Preloader { - return psql.Preload[*User, UserSlice](psql.PreloadRel{ - Name: "SetPendingByUser", - Sides: []psql.PreloadSide{ - { - From: Communications, - To: Users, - FromColumns: []string{"set_pending_by"}, - ToColumns: []string{"id"}, - }, - }, - }, Users.Columns.Names(), opts...) - }, - SetPossibleIssueByUser: func(opts ...psql.PreloadOption) psql.Preloader { - return psql.Preload[*User, UserSlice](psql.PreloadRel{ - Name: "SetPossibleIssueByUser", - Sides: []psql.PreloadSide{ - { - From: Communications, - To: Users, - FromColumns: []string{"set_possible_issue_by"}, - ToColumns: []string{"id"}, - }, - }, - }, Users.Columns.Names(), opts...) - }, - SetPossibleResolvedByUser: func(opts ...psql.PreloadOption) psql.Preloader { - return psql.Preload[*User, UserSlice](psql.PreloadRel{ - Name: "SetPossibleResolvedByUser", - Sides: []psql.PreloadSide{ - { - From: Communications, - To: Users, - FromColumns: []string{"set_possible_resolved_by"}, - ToColumns: []string{"id"}, - }, - }, - }, Users.Columns.Names(), opts...) - }, SourceEmailLogEmailLog: func(opts ...psql.PreloadOption) psql.Preloader { return psql.Preload[*CommsEmailLog, CommsEmailLogSlice](psql.PreloadRel{ Name: "SourceEmailLogEmailLog", @@ -2043,30 +1282,16 @@ func buildCommunicationPreloader() communicationPreloader { } type communicationThenLoader[Q orm.Loadable] struct { - ClosedByUser func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] - InvalidatedByUser func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] - OpenedByUser func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] - Organization func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] - ResponseEmailLogEmailLog func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] - ResponseTextLogTextLog func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] - SetPendingByUser func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] - SetPossibleIssueByUser func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] - SetPossibleResolvedByUser func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] - SourceEmailLogEmailLog func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] - SourceReportReport func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] - SourceTextLogTextLog func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] + Organization func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] + ResponseEmailLogEmailLog func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] + ResponseTextLogTextLog func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] + SourceEmailLogEmailLog func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] + SourceReportReport func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] + SourceTextLogTextLog func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] + CommunicationLogEntries func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] } func buildCommunicationThenLoader[Q orm.Loadable]() communicationThenLoader[Q] { - type ClosedByUserLoadInterface interface { - LoadClosedByUser(context.Context, bob.Executor, ...bob.Mod[*dialect.SelectQuery]) error - } - type InvalidatedByUserLoadInterface interface { - LoadInvalidatedByUser(context.Context, bob.Executor, ...bob.Mod[*dialect.SelectQuery]) error - } - type OpenedByUserLoadInterface interface { - LoadOpenedByUser(context.Context, bob.Executor, ...bob.Mod[*dialect.SelectQuery]) error - } type OrganizationLoadInterface interface { LoadOrganization(context.Context, bob.Executor, ...bob.Mod[*dialect.SelectQuery]) error } @@ -2076,15 +1301,6 @@ func buildCommunicationThenLoader[Q orm.Loadable]() communicationThenLoader[Q] { type ResponseTextLogTextLogLoadInterface interface { LoadResponseTextLogTextLog(context.Context, bob.Executor, ...bob.Mod[*dialect.SelectQuery]) error } - type SetPendingByUserLoadInterface interface { - LoadSetPendingByUser(context.Context, bob.Executor, ...bob.Mod[*dialect.SelectQuery]) error - } - type SetPossibleIssueByUserLoadInterface interface { - LoadSetPossibleIssueByUser(context.Context, bob.Executor, ...bob.Mod[*dialect.SelectQuery]) error - } - type SetPossibleResolvedByUserLoadInterface interface { - LoadSetPossibleResolvedByUser(context.Context, bob.Executor, ...bob.Mod[*dialect.SelectQuery]) error - } type SourceEmailLogEmailLogLoadInterface interface { LoadSourceEmailLogEmailLog(context.Context, bob.Executor, ...bob.Mod[*dialect.SelectQuery]) error } @@ -2094,26 +1310,11 @@ func buildCommunicationThenLoader[Q orm.Loadable]() communicationThenLoader[Q] { type SourceTextLogTextLogLoadInterface interface { LoadSourceTextLogTextLog(context.Context, bob.Executor, ...bob.Mod[*dialect.SelectQuery]) error } + type CommunicationLogEntriesLoadInterface interface { + LoadCommunicationLogEntries(context.Context, bob.Executor, ...bob.Mod[*dialect.SelectQuery]) error + } return communicationThenLoader[Q]{ - ClosedByUser: thenLoadBuilder[Q]( - "ClosedByUser", - func(ctx context.Context, exec bob.Executor, retrieved ClosedByUserLoadInterface, mods ...bob.Mod[*dialect.SelectQuery]) error { - return retrieved.LoadClosedByUser(ctx, exec, mods...) - }, - ), - InvalidatedByUser: thenLoadBuilder[Q]( - "InvalidatedByUser", - func(ctx context.Context, exec bob.Executor, retrieved InvalidatedByUserLoadInterface, mods ...bob.Mod[*dialect.SelectQuery]) error { - return retrieved.LoadInvalidatedByUser(ctx, exec, mods...) - }, - ), - OpenedByUser: thenLoadBuilder[Q]( - "OpenedByUser", - func(ctx context.Context, exec bob.Executor, retrieved OpenedByUserLoadInterface, mods ...bob.Mod[*dialect.SelectQuery]) error { - return retrieved.LoadOpenedByUser(ctx, exec, mods...) - }, - ), Organization: thenLoadBuilder[Q]( "Organization", func(ctx context.Context, exec bob.Executor, retrieved OrganizationLoadInterface, mods ...bob.Mod[*dialect.SelectQuery]) error { @@ -2132,24 +1333,6 @@ func buildCommunicationThenLoader[Q orm.Loadable]() communicationThenLoader[Q] { return retrieved.LoadResponseTextLogTextLog(ctx, exec, mods...) }, ), - SetPendingByUser: thenLoadBuilder[Q]( - "SetPendingByUser", - func(ctx context.Context, exec bob.Executor, retrieved SetPendingByUserLoadInterface, mods ...bob.Mod[*dialect.SelectQuery]) error { - return retrieved.LoadSetPendingByUser(ctx, exec, mods...) - }, - ), - SetPossibleIssueByUser: thenLoadBuilder[Q]( - "SetPossibleIssueByUser", - func(ctx context.Context, exec bob.Executor, retrieved SetPossibleIssueByUserLoadInterface, mods ...bob.Mod[*dialect.SelectQuery]) error { - return retrieved.LoadSetPossibleIssueByUser(ctx, exec, mods...) - }, - ), - SetPossibleResolvedByUser: thenLoadBuilder[Q]( - "SetPossibleResolvedByUser", - func(ctx context.Context, exec bob.Executor, retrieved SetPossibleResolvedByUserLoadInterface, mods ...bob.Mod[*dialect.SelectQuery]) error { - return retrieved.LoadSetPossibleResolvedByUser(ctx, exec, mods...) - }, - ), SourceEmailLogEmailLog: thenLoadBuilder[Q]( "SourceEmailLogEmailLog", func(ctx context.Context, exec bob.Executor, retrieved SourceEmailLogEmailLogLoadInterface, mods ...bob.Mod[*dialect.SelectQuery]) error { @@ -2168,174 +1351,15 @@ func buildCommunicationThenLoader[Q orm.Loadable]() communicationThenLoader[Q] { return retrieved.LoadSourceTextLogTextLog(ctx, exec, mods...) }, ), + CommunicationLogEntries: thenLoadBuilder[Q]( + "CommunicationLogEntries", + func(ctx context.Context, exec bob.Executor, retrieved CommunicationLogEntriesLoadInterface, mods ...bob.Mod[*dialect.SelectQuery]) error { + return retrieved.LoadCommunicationLogEntries(ctx, exec, mods...) + }, + ), } } -// LoadClosedByUser loads the communication's ClosedByUser into the .R struct -func (o *Communication) LoadClosedByUser(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error { - if o == nil { - return nil - } - - // Reset the relationship - o.R.ClosedByUser = nil - - related, err := o.ClosedByUser(mods...).One(ctx, exec) - if err != nil { - return err - } - - related.R.ClosedByCommunications = CommunicationSlice{o} - - o.R.ClosedByUser = related - return nil -} - -// LoadClosedByUser loads the communication's ClosedByUser into the .R struct -func (os CommunicationSlice) LoadClosedByUser(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error { - if len(os) == 0 { - return nil - } - - users, err := os.ClosedByUser(mods...).All(ctx, exec) - if err != nil { - return err - } - - for _, o := range os { - if o == nil { - continue - } - - for _, rel := range users { - if !o.ClosedBy.IsValue() { - continue - } - - if !(o.ClosedBy.IsValue() && o.ClosedBy.MustGet() == rel.ID) { - continue - } - - rel.R.ClosedByCommunications = append(rel.R.ClosedByCommunications, o) - - o.R.ClosedByUser = rel - break - } - } - - return nil -} - -// LoadInvalidatedByUser loads the communication's InvalidatedByUser into the .R struct -func (o *Communication) LoadInvalidatedByUser(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error { - if o == nil { - return nil - } - - // Reset the relationship - o.R.InvalidatedByUser = nil - - related, err := o.InvalidatedByUser(mods...).One(ctx, exec) - if err != nil { - return err - } - - related.R.InvalidatedByCommunications = CommunicationSlice{o} - - o.R.InvalidatedByUser = related - return nil -} - -// LoadInvalidatedByUser loads the communication's InvalidatedByUser into the .R struct -func (os CommunicationSlice) LoadInvalidatedByUser(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error { - if len(os) == 0 { - return nil - } - - users, err := os.InvalidatedByUser(mods...).All(ctx, exec) - if err != nil { - return err - } - - for _, o := range os { - if o == nil { - continue - } - - for _, rel := range users { - if !o.InvalidatedBy.IsValue() { - continue - } - - if !(o.InvalidatedBy.IsValue() && o.InvalidatedBy.MustGet() == rel.ID) { - continue - } - - rel.R.InvalidatedByCommunications = append(rel.R.InvalidatedByCommunications, o) - - o.R.InvalidatedByUser = rel - break - } - } - - return nil -} - -// LoadOpenedByUser loads the communication's OpenedByUser into the .R struct -func (o *Communication) LoadOpenedByUser(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error { - if o == nil { - return nil - } - - // Reset the relationship - o.R.OpenedByUser = nil - - related, err := o.OpenedByUser(mods...).One(ctx, exec) - if err != nil { - return err - } - - related.R.OpenedByCommunications = CommunicationSlice{o} - - o.R.OpenedByUser = related - return nil -} - -// LoadOpenedByUser loads the communication's OpenedByUser into the .R struct -func (os CommunicationSlice) LoadOpenedByUser(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error { - if len(os) == 0 { - return nil - } - - users, err := os.OpenedByUser(mods...).All(ctx, exec) - if err != nil { - return err - } - - for _, o := range os { - if o == nil { - continue - } - - for _, rel := range users { - if !o.OpenedBy.IsValue() { - continue - } - - if !(o.OpenedBy.IsValue() && o.OpenedBy.MustGet() == rel.ID) { - continue - } - - rel.R.OpenedByCommunications = append(rel.R.OpenedByCommunications, o) - - o.R.OpenedByUser = rel - break - } - } - - return nil -} - // LoadOrganization loads the communication's Organization into the .R struct func (o *Communication) LoadOrganization(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error { if o == nil { @@ -2498,171 +1522,6 @@ func (os CommunicationSlice) LoadResponseTextLogTextLog(ctx context.Context, exe return nil } -// LoadSetPendingByUser loads the communication's SetPendingByUser into the .R struct -func (o *Communication) LoadSetPendingByUser(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error { - if o == nil { - return nil - } - - // Reset the relationship - o.R.SetPendingByUser = nil - - related, err := o.SetPendingByUser(mods...).One(ctx, exec) - if err != nil { - return err - } - - related.R.SetPendingByCommunications = CommunicationSlice{o} - - o.R.SetPendingByUser = related - return nil -} - -// LoadSetPendingByUser loads the communication's SetPendingByUser into the .R struct -func (os CommunicationSlice) LoadSetPendingByUser(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error { - if len(os) == 0 { - return nil - } - - users, err := os.SetPendingByUser(mods...).All(ctx, exec) - if err != nil { - return err - } - - for _, o := range os { - if o == nil { - continue - } - - for _, rel := range users { - if !o.SetPendingBy.IsValue() { - continue - } - - if !(o.SetPendingBy.IsValue() && o.SetPendingBy.MustGet() == rel.ID) { - continue - } - - rel.R.SetPendingByCommunications = append(rel.R.SetPendingByCommunications, o) - - o.R.SetPendingByUser = rel - break - } - } - - return nil -} - -// LoadSetPossibleIssueByUser loads the communication's SetPossibleIssueByUser into the .R struct -func (o *Communication) LoadSetPossibleIssueByUser(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error { - if o == nil { - return nil - } - - // Reset the relationship - o.R.SetPossibleIssueByUser = nil - - related, err := o.SetPossibleIssueByUser(mods...).One(ctx, exec) - if err != nil { - return err - } - - related.R.SetPossibleIssueByCommunications = CommunicationSlice{o} - - o.R.SetPossibleIssueByUser = related - return nil -} - -// LoadSetPossibleIssueByUser loads the communication's SetPossibleIssueByUser into the .R struct -func (os CommunicationSlice) LoadSetPossibleIssueByUser(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error { - if len(os) == 0 { - return nil - } - - users, err := os.SetPossibleIssueByUser(mods...).All(ctx, exec) - if err != nil { - return err - } - - for _, o := range os { - if o == nil { - continue - } - - for _, rel := range users { - if !o.SetPossibleIssueBy.IsValue() { - continue - } - - if !(o.SetPossibleIssueBy.IsValue() && o.SetPossibleIssueBy.MustGet() == rel.ID) { - continue - } - - rel.R.SetPossibleIssueByCommunications = append(rel.R.SetPossibleIssueByCommunications, o) - - o.R.SetPossibleIssueByUser = rel - break - } - } - - return nil -} - -// LoadSetPossibleResolvedByUser loads the communication's SetPossibleResolvedByUser into the .R struct -func (o *Communication) LoadSetPossibleResolvedByUser(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error { - if o == nil { - return nil - } - - // Reset the relationship - o.R.SetPossibleResolvedByUser = nil - - related, err := o.SetPossibleResolvedByUser(mods...).One(ctx, exec) - if err != nil { - return err - } - - related.R.SetPossibleResolvedByCommunications = CommunicationSlice{o} - - o.R.SetPossibleResolvedByUser = related - return nil -} - -// LoadSetPossibleResolvedByUser loads the communication's SetPossibleResolvedByUser into the .R struct -func (os CommunicationSlice) LoadSetPossibleResolvedByUser(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error { - if len(os) == 0 { - return nil - } - - users, err := os.SetPossibleResolvedByUser(mods...).All(ctx, exec) - if err != nil { - return err - } - - for _, o := range os { - if o == nil { - continue - } - - for _, rel := range users { - if !o.SetPossibleResolvedBy.IsValue() { - continue - } - - if !(o.SetPossibleResolvedBy.IsValue() && o.SetPossibleResolvedBy.MustGet() == rel.ID) { - continue - } - - rel.R.SetPossibleResolvedByCommunications = append(rel.R.SetPossibleResolvedByCommunications, o) - - o.R.SetPossibleResolvedByUser = rel - break - } - } - - return nil -} - // LoadSourceEmailLogEmailLog loads the communication's SourceEmailLogEmailLog into the .R struct func (o *Communication) LoadSourceEmailLogEmailLog(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error { if o == nil { @@ -2827,3 +1686,64 @@ func (os CommunicationSlice) LoadSourceTextLogTextLog(ctx context.Context, exec return nil } + +// LoadCommunicationLogEntries loads the communication's CommunicationLogEntries into the .R struct +func (o *Communication) LoadCommunicationLogEntries(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error { + if o == nil { + return nil + } + + // Reset the relationship + o.R.CommunicationLogEntries = nil + + related, err := o.CommunicationLogEntries(mods...).All(ctx, exec) + if err != nil { + return err + } + + for _, rel := range related { + rel.R.Communication = o + } + + o.R.CommunicationLogEntries = related + return nil +} + +// LoadCommunicationLogEntries loads the communication's CommunicationLogEntries into the .R struct +func (os CommunicationSlice) LoadCommunicationLogEntries(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error { + if len(os) == 0 { + return nil + } + + communicationLogEntries, err := os.CommunicationLogEntries(mods...).All(ctx, exec) + if err != nil { + return err + } + + for _, o := range os { + if o == nil { + continue + } + + o.R.CommunicationLogEntries = nil + } + + for _, o := range os { + if o == nil { + continue + } + + for _, rel := range communicationLogEntries { + + if !(o.ID == rel.CommunicationID) { + continue + } + + rel.R.Communication = o + + o.R.CommunicationLogEntries = append(o.R.CommunicationLogEntries, rel) + } + } + + return nil +} diff --git a/db/models/communication_log_entry.bob.go b/db/models/communication_log_entry.bob.go new file mode 100644 index 00000000..626cafa9 --- /dev/null +++ b/db/models/communication_log_entry.bob.go @@ -0,0 +1,815 @@ +// Code generated by BobGen psql v0.42.5. 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/Gleipnir-Technology/bob" + "github.com/Gleipnir-Technology/bob/dialect/psql" + "github.com/Gleipnir-Technology/bob/dialect/psql/dialect" + "github.com/Gleipnir-Technology/bob/dialect/psql/dm" + "github.com/Gleipnir-Technology/bob/dialect/psql/sm" + "github.com/Gleipnir-Technology/bob/dialect/psql/um" + "github.com/Gleipnir-Technology/bob/expr" + "github.com/Gleipnir-Technology/bob/orm" + "github.com/Gleipnir-Technology/bob/types/pgtypes" + enums "github.com/Gleipnir-Technology/nidus-sync/db/enums" + "github.com/aarondl/opt/null" + "github.com/aarondl/opt/omit" + "github.com/aarondl/opt/omitnull" +) + +// CommunicationLogEntry is an object representing the database table. +type CommunicationLogEntry struct { + CommunicationID int32 `db:"communication_id" ` + Created time.Time `db:"created" ` + ID int32 `db:"id,pk" ` + Type enums.Communicationlogentry `db:"type_" ` + User null.Val[int32] `db:"user_" ` + + R communicationLogEntryR `db:"-" ` +} + +// CommunicationLogEntrySlice is an alias for a slice of pointers to CommunicationLogEntry. +// This should almost always be used instead of []*CommunicationLogEntry. +type CommunicationLogEntrySlice []*CommunicationLogEntry + +// CommunicationLogEntries contains methods to work with the communication_log_entry table +var CommunicationLogEntries = psql.NewTablex[*CommunicationLogEntry, CommunicationLogEntrySlice, *CommunicationLogEntrySetter]("", "communication_log_entry", buildCommunicationLogEntryColumns("communication_log_entry")) + +// CommunicationLogEntriesQuery is a query on the communication_log_entry table +type CommunicationLogEntriesQuery = *psql.ViewQuery[*CommunicationLogEntry, CommunicationLogEntrySlice] + +// communicationLogEntryR is where relationships are stored. +type communicationLogEntryR struct { + Communication *Communication // communication_log_entry.communication_log_entry_communication_id_fkey + User *User // communication_log_entry.communication_log_entry_user__fkey +} + +func buildCommunicationLogEntryColumns(alias string) communicationLogEntryColumns { + return communicationLogEntryColumns{ + ColumnsExpr: expr.NewColumnsExpr( + "communication_id", "created", "id", "type_", "user_", + ).WithParent("communication_log_entry"), + tableAlias: alias, + CommunicationID: psql.Quote(alias, "communication_id"), + Created: psql.Quote(alias, "created"), + ID: psql.Quote(alias, "id"), + Type: psql.Quote(alias, "type_"), + User: psql.Quote(alias, "user_"), + } +} + +type communicationLogEntryColumns struct { + expr.ColumnsExpr + tableAlias string + CommunicationID psql.Expression + Created psql.Expression + ID psql.Expression + Type psql.Expression + User psql.Expression +} + +func (c communicationLogEntryColumns) Alias() string { + return c.tableAlias +} + +func (communicationLogEntryColumns) AliasedAs(alias string) communicationLogEntryColumns { + return buildCommunicationLogEntryColumns(alias) +} + +// CommunicationLogEntrySetter is used for insert/upsert/update operations +// All values are optional, and do not have to be set +// Generated columns are not included +type CommunicationLogEntrySetter struct { + CommunicationID omit.Val[int32] `db:"communication_id" ` + Created omit.Val[time.Time] `db:"created" ` + ID omit.Val[int32] `db:"id,pk" ` + Type omit.Val[enums.Communicationlogentry] `db:"type_" ` + User omitnull.Val[int32] `db:"user_" ` +} + +func (s CommunicationLogEntrySetter) SetColumns() []string { + vals := make([]string, 0, 5) + if s.CommunicationID.IsValue() { + vals = append(vals, "communication_id") + } + if s.Created.IsValue() { + vals = append(vals, "created") + } + if s.ID.IsValue() { + vals = append(vals, "id") + } + if s.Type.IsValue() { + vals = append(vals, "type_") + } + if !s.User.IsUnset() { + vals = append(vals, "user_") + } + return vals +} + +func (s CommunicationLogEntrySetter) Overwrite(t *CommunicationLogEntry) { + if s.CommunicationID.IsValue() { + t.CommunicationID = s.CommunicationID.MustGet() + } + if s.Created.IsValue() { + t.Created = s.Created.MustGet() + } + if s.ID.IsValue() { + t.ID = s.ID.MustGet() + } + if s.Type.IsValue() { + t.Type = s.Type.MustGet() + } + if !s.User.IsUnset() { + t.User = s.User.MustGetNull() + } +} + +func (s *CommunicationLogEntrySetter) Apply(q *dialect.InsertQuery) { + q.AppendHooks(func(ctx context.Context, exec bob.Executor) (context.Context, error) { + return CommunicationLogEntries.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.CommunicationID.IsValue() { + vals[0] = psql.Arg(s.CommunicationID.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.ID.IsValue() { + vals[2] = psql.Arg(s.ID.MustGet()) + } else { + vals[2] = psql.Raw("DEFAULT") + } + + if s.Type.IsValue() { + vals[3] = psql.Arg(s.Type.MustGet()) + } else { + vals[3] = psql.Raw("DEFAULT") + } + + if !s.User.IsUnset() { + vals[4] = psql.Arg(s.User.MustGetNull()) + } else { + vals[4] = psql.Raw("DEFAULT") + } + + return bob.ExpressSlice(ctx, w, d, start, vals, "", ", ", "") + })) +} + +func (s CommunicationLogEntrySetter) UpdateMod() bob.Mod[*dialect.UpdateQuery] { + return um.Set(s.Expressions()...) +} + +func (s CommunicationLogEntrySetter) Expressions(prefix ...string) []bob.Expression { + exprs := make([]bob.Expression, 0, 5) + + if s.CommunicationID.IsValue() { + exprs = append(exprs, expr.Join{Sep: " = ", Exprs: []bob.Expression{ + psql.Quote(append(prefix, "communication_id")...), + psql.Arg(s.CommunicationID), + }}) + } + + if s.Created.IsValue() { + exprs = append(exprs, expr.Join{Sep: " = ", Exprs: []bob.Expression{ + psql.Quote(append(prefix, "created")...), + psql.Arg(s.Created), + }}) + } + + if s.ID.IsValue() { + exprs = append(exprs, expr.Join{Sep: " = ", Exprs: []bob.Expression{ + psql.Quote(append(prefix, "id")...), + psql.Arg(s.ID), + }}) + } + + if s.Type.IsValue() { + exprs = append(exprs, expr.Join{Sep: " = ", Exprs: []bob.Expression{ + psql.Quote(append(prefix, "type_")...), + psql.Arg(s.Type), + }}) + } + + if !s.User.IsUnset() { + exprs = append(exprs, expr.Join{Sep: " = ", Exprs: []bob.Expression{ + psql.Quote(append(prefix, "user_")...), + psql.Arg(s.User), + }}) + } + + return exprs +} + +// FindCommunicationLogEntry retrieves a single record by primary key +// If cols is empty Find will return all columns. +func FindCommunicationLogEntry(ctx context.Context, exec bob.Executor, IDPK int32, cols ...string) (*CommunicationLogEntry, error) { + if len(cols) == 0 { + return CommunicationLogEntries.Query( + sm.Where(CommunicationLogEntries.Columns.ID.EQ(psql.Arg(IDPK))), + ).One(ctx, exec) + } + + return CommunicationLogEntries.Query( + sm.Where(CommunicationLogEntries.Columns.ID.EQ(psql.Arg(IDPK))), + sm.Columns(CommunicationLogEntries.Columns.Only(cols...)), + ).One(ctx, exec) +} + +// CommunicationLogEntryExists checks the presence of a single record by primary key +func CommunicationLogEntryExists(ctx context.Context, exec bob.Executor, IDPK int32) (bool, error) { + return CommunicationLogEntries.Query( + sm.Where(CommunicationLogEntries.Columns.ID.EQ(psql.Arg(IDPK))), + ).Exists(ctx, exec) +} + +// AfterQueryHook is called after CommunicationLogEntry is retrieved from the database +func (o *CommunicationLogEntry) AfterQueryHook(ctx context.Context, exec bob.Executor, queryType bob.QueryType) error { + var err error + + switch queryType { + case bob.QueryTypeSelect: + ctx, err = CommunicationLogEntries.AfterSelectHooks.RunHooks(ctx, exec, CommunicationLogEntrySlice{o}) + case bob.QueryTypeInsert: + ctx, err = CommunicationLogEntries.AfterInsertHooks.RunHooks(ctx, exec, CommunicationLogEntrySlice{o}) + case bob.QueryTypeUpdate: + ctx, err = CommunicationLogEntries.AfterUpdateHooks.RunHooks(ctx, exec, CommunicationLogEntrySlice{o}) + case bob.QueryTypeDelete: + ctx, err = CommunicationLogEntries.AfterDeleteHooks.RunHooks(ctx, exec, CommunicationLogEntrySlice{o}) + } + + return err +} + +// primaryKeyVals returns the primary key values of the CommunicationLogEntry +func (o *CommunicationLogEntry) primaryKeyVals() bob.Expression { + return psql.Arg(o.ID) +} + +func (o *CommunicationLogEntry) pkEQ() dialect.Expression { + return psql.Quote("communication_log_entry", "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 CommunicationLogEntry +func (o *CommunicationLogEntry) Update(ctx context.Context, exec bob.Executor, s *CommunicationLogEntrySetter) error { + v, err := CommunicationLogEntries.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 CommunicationLogEntry record with an executor +func (o *CommunicationLogEntry) Delete(ctx context.Context, exec bob.Executor) error { + _, err := CommunicationLogEntries.Delete(dm.Where(o.pkEQ())).Exec(ctx, exec) + return err +} + +// Reload refreshes the CommunicationLogEntry using the executor +func (o *CommunicationLogEntry) Reload(ctx context.Context, exec bob.Executor) error { + o2, err := CommunicationLogEntries.Query( + sm.Where(CommunicationLogEntries.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 CommunicationLogEntrySlice is retrieved from the database +func (o CommunicationLogEntrySlice) AfterQueryHook(ctx context.Context, exec bob.Executor, queryType bob.QueryType) error { + var err error + + switch queryType { + case bob.QueryTypeSelect: + ctx, err = CommunicationLogEntries.AfterSelectHooks.RunHooks(ctx, exec, o) + case bob.QueryTypeInsert: + ctx, err = CommunicationLogEntries.AfterInsertHooks.RunHooks(ctx, exec, o) + case bob.QueryTypeUpdate: + ctx, err = CommunicationLogEntries.AfterUpdateHooks.RunHooks(ctx, exec, o) + case bob.QueryTypeDelete: + ctx, err = CommunicationLogEntries.AfterDeleteHooks.RunHooks(ctx, exec, o) + } + + return err +} + +func (o CommunicationLogEntrySlice) pkIN() dialect.Expression { + if len(o) == 0 { + return psql.Raw("NULL") + } + + return psql.Quote("communication_log_entry", "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 CommunicationLogEntrySlice) copyMatchingRows(from ...*CommunicationLogEntry) { + 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 CommunicationLogEntrySlice) 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 CommunicationLogEntries.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 *CommunicationLogEntry: + o.copyMatchingRows(retrieved) + case []*CommunicationLogEntry: + o.copyMatchingRows(retrieved...) + case CommunicationLogEntrySlice: + o.copyMatchingRows(retrieved...) + default: + // If the retrieved value is not a CommunicationLogEntry or a slice of CommunicationLogEntry + // then run the AfterUpdateHooks on the slice + _, err = CommunicationLogEntries.AfterUpdateHooks.RunHooks(ctx, exec, o) + } + + return err + })) + + q.AppendWhere(o.pkIN()) + }) +} + +// DeleteMod modifies an delete query with "WHERE primary_key IN (o...)" +func (o CommunicationLogEntrySlice) 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 CommunicationLogEntries.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 *CommunicationLogEntry: + o.copyMatchingRows(retrieved) + case []*CommunicationLogEntry: + o.copyMatchingRows(retrieved...) + case CommunicationLogEntrySlice: + o.copyMatchingRows(retrieved...) + default: + // If the retrieved value is not a CommunicationLogEntry or a slice of CommunicationLogEntry + // then run the AfterDeleteHooks on the slice + _, err = CommunicationLogEntries.AfterDeleteHooks.RunHooks(ctx, exec, o) + } + + return err + })) + + q.AppendWhere(o.pkIN()) + }) +} + +func (o CommunicationLogEntrySlice) UpdateAll(ctx context.Context, exec bob.Executor, vals CommunicationLogEntrySetter) error { + if len(o) == 0 { + return nil + } + + _, err := CommunicationLogEntries.Update(vals.UpdateMod(), o.UpdateMod()).All(ctx, exec) + return err +} + +func (o CommunicationLogEntrySlice) DeleteAll(ctx context.Context, exec bob.Executor) error { + if len(o) == 0 { + return nil + } + + _, err := CommunicationLogEntries.Delete(o.DeleteMod()).Exec(ctx, exec) + return err +} + +func (o CommunicationLogEntrySlice) ReloadAll(ctx context.Context, exec bob.Executor) error { + if len(o) == 0 { + return nil + } + + o2, err := CommunicationLogEntries.Query(sm.Where(o.pkIN())).All(ctx, exec) + if err != nil { + return err + } + + o.copyMatchingRows(o2...) + + return nil +} + +// Communication starts a query for related objects on communication +func (o *CommunicationLogEntry) Communication(mods ...bob.Mod[*dialect.SelectQuery]) CommunicationsQuery { + return Communications.Query(append(mods, + sm.Where(Communications.Columns.ID.EQ(psql.Arg(o.CommunicationID))), + )...) +} + +func (os CommunicationLogEntrySlice) Communication(mods ...bob.Mod[*dialect.SelectQuery]) CommunicationsQuery { + pkCommunicationID := make(pgtypes.Array[int32], 0, len(os)) + for _, o := range os { + if o == nil { + continue + } + pkCommunicationID = append(pkCommunicationID, o.CommunicationID) + } + PKArgExpr := psql.Select(sm.Columns( + psql.F("unnest", psql.Cast(psql.Arg(pkCommunicationID), "integer[]")), + )) + + return Communications.Query(append(mods, + sm.Where(psql.Group(Communications.Columns.ID).OP("IN", PKArgExpr)), + )...) +} + +// User starts a query for related objects on user_ +func (o *CommunicationLogEntry) RelatedUser(mods ...bob.Mod[*dialect.SelectQuery]) UsersQuery { + return Users.Query(append(mods, + sm.Where(Users.Columns.ID.EQ(psql.Arg(o.User))), + )...) +} + +func (os CommunicationLogEntrySlice) RelatedUser(mods ...bob.Mod[*dialect.SelectQuery]) UsersQuery { + pkUser := make(pgtypes.Array[null.Val[int32]], 0, len(os)) + for _, o := range os { + if o == nil { + continue + } + pkUser = append(pkUser, o.User) + } + PKArgExpr := psql.Select(sm.Columns( + psql.F("unnest", psql.Cast(psql.Arg(pkUser), "integer[]")), + )) + + return Users.Query(append(mods, + sm.Where(psql.Group(Users.Columns.ID).OP("IN", PKArgExpr)), + )...) +} + +func attachCommunicationLogEntryCommunication0(ctx context.Context, exec bob.Executor, count int, communicationLogEntry0 *CommunicationLogEntry, communication1 *Communication) (*CommunicationLogEntry, error) { + setter := &CommunicationLogEntrySetter{ + CommunicationID: omit.From(communication1.ID), + } + + err := communicationLogEntry0.Update(ctx, exec, setter) + if err != nil { + return nil, fmt.Errorf("attachCommunicationLogEntryCommunication0: %w", err) + } + + return communicationLogEntry0, nil +} + +func (communicationLogEntry0 *CommunicationLogEntry) InsertCommunication(ctx context.Context, exec bob.Executor, related *CommunicationSetter) error { + var err error + + communication1, err := Communications.Insert(related).One(ctx, exec) + if err != nil { + return fmt.Errorf("inserting related objects: %w", err) + } + + _, err = attachCommunicationLogEntryCommunication0(ctx, exec, 1, communicationLogEntry0, communication1) + if err != nil { + return err + } + + communicationLogEntry0.R.Communication = communication1 + + communication1.R.CommunicationLogEntries = append(communication1.R.CommunicationLogEntries, communicationLogEntry0) + + return nil +} + +func (communicationLogEntry0 *CommunicationLogEntry) AttachCommunication(ctx context.Context, exec bob.Executor, communication1 *Communication) error { + var err error + + _, err = attachCommunicationLogEntryCommunication0(ctx, exec, 1, communicationLogEntry0, communication1) + if err != nil { + return err + } + + communicationLogEntry0.R.Communication = communication1 + + communication1.R.CommunicationLogEntries = append(communication1.R.CommunicationLogEntries, communicationLogEntry0) + + return nil +} + +func attachCommunicationLogEntryUser0(ctx context.Context, exec bob.Executor, count int, communicationLogEntry0 *CommunicationLogEntry, user1 *User) (*CommunicationLogEntry, error) { + setter := &CommunicationLogEntrySetter{ + User: omitnull.From(user1.ID), + } + + err := communicationLogEntry0.Update(ctx, exec, setter) + if err != nil { + return nil, fmt.Errorf("attachCommunicationLogEntryUser0: %w", err) + } + + return communicationLogEntry0, nil +} + +func (communicationLogEntry0 *CommunicationLogEntry) InsertUser(ctx context.Context, exec bob.Executor, related *UserSetter) error { + var err error + + user1, err := Users.Insert(related).One(ctx, exec) + if err != nil { + return fmt.Errorf("inserting related objects: %w", err) + } + + _, err = attachCommunicationLogEntryUser0(ctx, exec, 1, communicationLogEntry0, user1) + if err != nil { + return err + } + + communicationLogEntry0.R.User = user1 + + user1.R.CommunicationLogEntries = append(user1.R.CommunicationLogEntries, communicationLogEntry0) + + return nil +} + +func (communicationLogEntry0 *CommunicationLogEntry) AttachUser(ctx context.Context, exec bob.Executor, user1 *User) error { + var err error + + _, err = attachCommunicationLogEntryUser0(ctx, exec, 1, communicationLogEntry0, user1) + if err != nil { + return err + } + + communicationLogEntry0.R.User = user1 + + user1.R.CommunicationLogEntries = append(user1.R.CommunicationLogEntries, communicationLogEntry0) + + return nil +} + +type communicationLogEntryWhere[Q psql.Filterable] struct { + CommunicationID psql.WhereMod[Q, int32] + Created psql.WhereMod[Q, time.Time] + ID psql.WhereMod[Q, int32] + Type psql.WhereMod[Q, enums.Communicationlogentry] + User psql.WhereNullMod[Q, int32] +} + +func (communicationLogEntryWhere[Q]) AliasedAs(alias string) communicationLogEntryWhere[Q] { + return buildCommunicationLogEntryWhere[Q](buildCommunicationLogEntryColumns(alias)) +} + +func buildCommunicationLogEntryWhere[Q psql.Filterable](cols communicationLogEntryColumns) communicationLogEntryWhere[Q] { + return communicationLogEntryWhere[Q]{ + CommunicationID: psql.Where[Q, int32](cols.CommunicationID), + Created: psql.Where[Q, time.Time](cols.Created), + ID: psql.Where[Q, int32](cols.ID), + Type: psql.Where[Q, enums.Communicationlogentry](cols.Type), + User: psql.WhereNull[Q, int32](cols.User), + } +} + +func (o *CommunicationLogEntry) Preload(name string, retrieved any) error { + if o == nil { + return nil + } + + switch name { + case "Communication": + rel, ok := retrieved.(*Communication) + if !ok { + return fmt.Errorf("communicationLogEntry cannot load %T as %q", retrieved, name) + } + + o.R.Communication = rel + + if rel != nil { + rel.R.CommunicationLogEntries = CommunicationLogEntrySlice{o} + } + return nil + case "User": + rel, ok := retrieved.(*User) + if !ok { + return fmt.Errorf("communicationLogEntry cannot load %T as %q", retrieved, name) + } + + o.R.User = rel + + if rel != nil { + rel.R.CommunicationLogEntries = CommunicationLogEntrySlice{o} + } + return nil + default: + return fmt.Errorf("communicationLogEntry has no relationship %q", name) + } +} + +type communicationLogEntryPreloader struct { + Communication func(...psql.PreloadOption) psql.Preloader + User func(...psql.PreloadOption) psql.Preloader +} + +func buildCommunicationLogEntryPreloader() communicationLogEntryPreloader { + return communicationLogEntryPreloader{ + Communication: func(opts ...psql.PreloadOption) psql.Preloader { + return psql.Preload[*Communication, CommunicationSlice](psql.PreloadRel{ + Name: "Communication", + Sides: []psql.PreloadSide{ + { + From: CommunicationLogEntries, + To: Communications, + FromColumns: []string{"communication_id"}, + ToColumns: []string{"id"}, + }, + }, + }, Communications.Columns.Names(), opts...) + }, + User: func(opts ...psql.PreloadOption) psql.Preloader { + return psql.Preload[*User, UserSlice](psql.PreloadRel{ + Name: "User", + Sides: []psql.PreloadSide{ + { + From: CommunicationLogEntries, + To: Users, + FromColumns: []string{"user_"}, + ToColumns: []string{"id"}, + }, + }, + }, Users.Columns.Names(), opts...) + }, + } +} + +type communicationLogEntryThenLoader[Q orm.Loadable] struct { + Communication func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] + User func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] +} + +func buildCommunicationLogEntryThenLoader[Q orm.Loadable]() communicationLogEntryThenLoader[Q] { + type CommunicationLoadInterface interface { + LoadCommunication(context.Context, bob.Executor, ...bob.Mod[*dialect.SelectQuery]) error + } + type UserLoadInterface interface { + LoadUser(context.Context, bob.Executor, ...bob.Mod[*dialect.SelectQuery]) error + } + + return communicationLogEntryThenLoader[Q]{ + Communication: thenLoadBuilder[Q]( + "Communication", + func(ctx context.Context, exec bob.Executor, retrieved CommunicationLoadInterface, mods ...bob.Mod[*dialect.SelectQuery]) error { + return retrieved.LoadCommunication(ctx, exec, mods...) + }, + ), + User: thenLoadBuilder[Q]( + "User", + func(ctx context.Context, exec bob.Executor, retrieved UserLoadInterface, mods ...bob.Mod[*dialect.SelectQuery]) error { + return retrieved.LoadUser(ctx, exec, mods...) + }, + ), + } +} + +// LoadCommunication loads the communicationLogEntry's Communication into the .R struct +func (o *CommunicationLogEntry) LoadCommunication(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error { + if o == nil { + return nil + } + + // Reset the relationship + o.R.Communication = nil + + related, err := o.Communication(mods...).One(ctx, exec) + if err != nil { + return err + } + + related.R.CommunicationLogEntries = CommunicationLogEntrySlice{o} + + o.R.Communication = related + return nil +} + +// LoadCommunication loads the communicationLogEntry's Communication into the .R struct +func (os CommunicationLogEntrySlice) LoadCommunication(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error { + if len(os) == 0 { + return nil + } + + communications, err := os.Communication(mods...).All(ctx, exec) + if err != nil { + return err + } + + for _, o := range os { + if o == nil { + continue + } + + for _, rel := range communications { + + if !(o.CommunicationID == rel.ID) { + continue + } + + rel.R.CommunicationLogEntries = append(rel.R.CommunicationLogEntries, o) + + o.R.Communication = rel + break + } + } + + return nil +} + +// LoadUser loads the communicationLogEntry's User into the .R struct +func (o *CommunicationLogEntry) LoadUser(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error { + if o == nil { + return nil + } + + // Reset the relationship + o.R.User = nil + + related, err := o.RelatedUser(mods...).One(ctx, exec) + if err != nil { + return err + } + + related.R.CommunicationLogEntries = CommunicationLogEntrySlice{o} + + o.R.User = related + return nil +} + +// LoadUser loads the communicationLogEntry's User into the .R struct +func (os CommunicationLogEntrySlice) LoadUser(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error { + if len(os) == 0 { + return nil + } + + users, err := os.RelatedUser(mods...).All(ctx, exec) + if err != nil { + return err + } + + for _, o := range os { + if o == nil { + continue + } + + for _, rel := range users { + if !o.User.IsValue() { + continue + } + + if !(o.User.IsValue() && o.User.MustGet() == rel.ID) { + continue + } + + rel.R.CommunicationLogEntries = append(rel.R.CommunicationLogEntries, o) + + o.R.User = rel + break + } + } + + return nil +} diff --git a/db/models/publicreport.compliance.bob.go b/db/models/publicreport.compliance.bob.go index b9a38e18..2b47988f 100644 --- a/db/models/publicreport.compliance.bob.go +++ b/db/models/publicreport.compliance.bob.go @@ -26,16 +26,16 @@ import ( // PublicreportCompliance is an object representing the database table. type PublicreportCompliance struct { - AccessInstructions string `db:"access_instructions" ` - AvailabilityNotes string `db:"availability_notes" ` - Comments string `db:"comments" ` - GateCode string `db:"gate_code" ` - HasDog null.Val[bool] `db:"has_dog" ` - PermissionType enums.PublicreportPermissionaccesstype `db:"permission_type" ` - ReportID int32 `db:"report_id,pk" ` - ReportPhoneCanText null.Val[bool] `db:"report_phone_can_text" ` - WantsScheduled null.Val[bool] `db:"wants_scheduled" ` - Submitted null.Val[time.Time] `db:"submitted" ` + AccessInstructions string `db:"access_instructions" ` + AvailabilityNotes string `db:"availability_notes" ` + Comments string `db:"comments" ` + GateCode string `db:"gate_code" ` + HasDog null.Val[bool] `db:"has_dog" ` + PermissionType enums.PublicreportPermissionaccess `db:"permission_type" ` + ReportID int32 `db:"report_id,pk" ` + ReportPhoneCanText null.Val[bool] `db:"report_phone_can_text" ` + WantsScheduled null.Val[bool] `db:"wants_scheduled" ` + Submitted null.Val[time.Time] `db:"submitted" ` R publicreportComplianceR `db:"-" ` } @@ -101,16 +101,16 @@ func (publicreportComplianceColumns) AliasedAs(alias string) publicreportComplia // All values are optional, and do not have to be set // Generated columns are not included type PublicreportComplianceSetter struct { - AccessInstructions omit.Val[string] `db:"access_instructions" ` - AvailabilityNotes omit.Val[string] `db:"availability_notes" ` - Comments omit.Val[string] `db:"comments" ` - GateCode omit.Val[string] `db:"gate_code" ` - HasDog omitnull.Val[bool] `db:"has_dog" ` - PermissionType omit.Val[enums.PublicreportPermissionaccesstype] `db:"permission_type" ` - ReportID omit.Val[int32] `db:"report_id,pk" ` - ReportPhoneCanText omitnull.Val[bool] `db:"report_phone_can_text" ` - WantsScheduled omitnull.Val[bool] `db:"wants_scheduled" ` - Submitted omitnull.Val[time.Time] `db:"submitted" ` + AccessInstructions omit.Val[string] `db:"access_instructions" ` + AvailabilityNotes omit.Val[string] `db:"availability_notes" ` + Comments omit.Val[string] `db:"comments" ` + GateCode omit.Val[string] `db:"gate_code" ` + HasDog omitnull.Val[bool] `db:"has_dog" ` + PermissionType omit.Val[enums.PublicreportPermissionaccess] `db:"permission_type" ` + ReportID omit.Val[int32] `db:"report_id,pk" ` + ReportPhoneCanText omitnull.Val[bool] `db:"report_phone_can_text" ` + WantsScheduled omitnull.Val[bool] `db:"wants_scheduled" ` + Submitted omitnull.Val[time.Time] `db:"submitted" ` } func (s PublicreportComplianceSetter) SetColumns() []string { @@ -633,7 +633,7 @@ type publicreportComplianceWhere[Q psql.Filterable] struct { Comments psql.WhereMod[Q, string] GateCode psql.WhereMod[Q, string] HasDog psql.WhereNullMod[Q, bool] - PermissionType psql.WhereMod[Q, enums.PublicreportPermissionaccesstype] + PermissionType psql.WhereMod[Q, enums.PublicreportPermissionaccess] ReportID psql.WhereMod[Q, int32] ReportPhoneCanText psql.WhereNullMod[Q, bool] WantsScheduled psql.WhereNullMod[Q, bool] @@ -651,7 +651,7 @@ func buildPublicreportComplianceWhere[Q psql.Filterable](cols publicreportCompli Comments: psql.Where[Q, string](cols.Comments), GateCode: psql.Where[Q, string](cols.GateCode), HasDog: psql.WhereNull[Q, bool](cols.HasDog), - PermissionType: psql.Where[Q, enums.PublicreportPermissionaccesstype](cols.PermissionType), + PermissionType: psql.Where[Q, enums.PublicreportPermissionaccess](cols.PermissionType), ReportID: psql.Where[Q, int32](cols.ReportID), ReportPhoneCanText: psql.WhereNull[Q, bool](cols.ReportPhoneCanText), WantsScheduled: psql.WhereNull[Q, bool](cols.WantsScheduled), diff --git a/db/models/user_.bob.go b/db/models/user_.bob.go index 9edca83d..7821cfb9 100644 --- a/db/models/user_.bob.go +++ b/db/models/user_.bob.go @@ -60,38 +60,33 @@ type UsersQuery = *psql.ViewQuery[*User, UserSlice] // userR is where relationships are stored. type userR struct { - CreatorTextJobs CommsTextJobSlice // comms.text_job.text_job_creator_id_fkey - ClosedByCommunications CommunicationSlice // communication.communication_closed_by_fkey - InvalidatedByCommunications CommunicationSlice // communication.communication_invalidated_by_fkey - OpenedByCommunications CommunicationSlice // communication.communication_opened_by_fkey - SetPendingByCommunications CommunicationSlice // communication.communication_set_pending_by_fkey - SetPossibleIssueByCommunications CommunicationSlice // communication.communication_set_possible_issue_by_fkey - SetPossibleResolvedByCommunications CommunicationSlice // communication.communication_set_possible_resolved_by_fkey - CreatorComplianceReportRequests ComplianceReportRequestSlice // compliance_report_request.compliance_report_request_creator_fkey - CreatorFeatures FeatureSlice // feature.feature_creator_id_fkey - CommitterFiles FileuploadFileSlice // fileupload.file.file_committer_fkey - CreatorFiles FileuploadFileSlice // fileupload.file.file_creator_id_fkey - FileuploadPool FileuploadPoolSlice // fileupload.pool.pool_creator_id_fkey - CreatorLeads LeadSlice // lead.lead_creator_fkey - ImpersonatorLogImpersonations LogImpersonationSlice // log_impersonation.log_impersonation_impersonator_id_fkey - TargetLogImpersonations LogImpersonationSlice // log_impersonation.log_impersonation_target_id_fkey - CreatorNoteAudios NoteAudioSlice // note_audio.note_audio_creator_id_fkey - DeletorNoteAudios NoteAudioSlice // note_audio.note_audio_deletor_id_fkey - CreatorNoteImages NoteImageSlice // note_image.note_image_creator_id_fkey - DeletorNoteImages NoteImageSlice // note_image.note_image_deletor_id_fkey - UserNotifications NotificationSlice // notification.notification_user_id_fkey - ReviewerNuisanceOlds PublicreportNuisanceOldSlice // publicreport.nuisance_old.nuisance_reviewer_id_fkey - ReviewerReports PublicreportReportSlice // publicreport.report.report_reviewer_id_fkey - UserReportLogs PublicreportReportLogSlice // publicreport.report_log.report_log_user_id_fkey - ReviewerWaterOlds PublicreportWaterOldSlice // publicreport.water_old.water_reviewer_id_fkey - CreatorReportTexts ReportTextSlice // report_text.report_text_creator_id_fkey - CreatorResidents ResidentSlice // resident.resident_creator_fkey - CreatorReviewTasks ReviewTaskSlice // review_task.review_task_creator_id_fkey - ReviewerReviewTasks ReviewTaskSlice // review_task.review_task_reviewer_id_fkey - AddressorSignals SignalSlice // signal.signal_addressor_fkey - CreatorSignals SignalSlice // signal.signal_creator_fkey - CreatorSites SiteSlice // site.site_creator_id_fkey - Organization *Organization // user_.user__organization_id_fkey + CreatorTextJobs CommsTextJobSlice // comms.text_job.text_job_creator_id_fkey + CommunicationLogEntries CommunicationLogEntrySlice // communication_log_entry.communication_log_entry_user__fkey + CreatorComplianceReportRequests ComplianceReportRequestSlice // compliance_report_request.compliance_report_request_creator_fkey + CreatorFeatures FeatureSlice // feature.feature_creator_id_fkey + CommitterFiles FileuploadFileSlice // fileupload.file.file_committer_fkey + CreatorFiles FileuploadFileSlice // fileupload.file.file_creator_id_fkey + FileuploadPool FileuploadPoolSlice // fileupload.pool.pool_creator_id_fkey + CreatorLeads LeadSlice // lead.lead_creator_fkey + ImpersonatorLogImpersonations LogImpersonationSlice // log_impersonation.log_impersonation_impersonator_id_fkey + TargetLogImpersonations LogImpersonationSlice // log_impersonation.log_impersonation_target_id_fkey + CreatorNoteAudios NoteAudioSlice // note_audio.note_audio_creator_id_fkey + DeletorNoteAudios NoteAudioSlice // note_audio.note_audio_deletor_id_fkey + CreatorNoteImages NoteImageSlice // note_image.note_image_creator_id_fkey + DeletorNoteImages NoteImageSlice // note_image.note_image_deletor_id_fkey + UserNotifications NotificationSlice // notification.notification_user_id_fkey + ReviewerNuisanceOlds PublicreportNuisanceOldSlice // publicreport.nuisance_old.nuisance_reviewer_id_fkey + ReviewerReports PublicreportReportSlice // publicreport.report.report_reviewer_id_fkey + UserReportLogs PublicreportReportLogSlice // publicreport.report_log.report_log_user_id_fkey + ReviewerWaterOlds PublicreportWaterOldSlice // publicreport.water_old.water_reviewer_id_fkey + CreatorReportTexts ReportTextSlice // report_text.report_text_creator_id_fkey + CreatorResidents ResidentSlice // resident.resident_creator_fkey + CreatorReviewTasks ReviewTaskSlice // review_task.review_task_creator_id_fkey + ReviewerReviewTasks ReviewTaskSlice // review_task.review_task_reviewer_id_fkey + AddressorSignals SignalSlice // signal.signal_addressor_fkey + CreatorSignals SignalSlice // signal.signal_creator_fkey + CreatorSites SiteSlice // site.site_creator_id_fkey + Organization *Organization // user_.user__organization_id_fkey } func buildUserColumns(alias string) userColumns { @@ -772,14 +767,14 @@ func (os UserSlice) CreatorTextJobs(mods ...bob.Mod[*dialect.SelectQuery]) Comms )...) } -// ClosedByCommunications starts a query for related objects on communication -func (o *User) ClosedByCommunications(mods ...bob.Mod[*dialect.SelectQuery]) CommunicationsQuery { - return Communications.Query(append(mods, - sm.Where(Communications.Columns.ClosedBy.EQ(psql.Arg(o.ID))), +// CommunicationLogEntries starts a query for related objects on communication_log_entry +func (o *User) CommunicationLogEntries(mods ...bob.Mod[*dialect.SelectQuery]) CommunicationLogEntriesQuery { + return CommunicationLogEntries.Query(append(mods, + sm.Where(CommunicationLogEntries.Columns.User.EQ(psql.Arg(o.ID))), )...) } -func (os UserSlice) ClosedByCommunications(mods ...bob.Mod[*dialect.SelectQuery]) CommunicationsQuery { +func (os UserSlice) CommunicationLogEntries(mods ...bob.Mod[*dialect.SelectQuery]) CommunicationLogEntriesQuery { pkID := make(pgtypes.Array[int32], 0, len(os)) for _, o := range os { if o == nil { @@ -791,128 +786,8 @@ func (os UserSlice) ClosedByCommunications(mods ...bob.Mod[*dialect.SelectQuery] psql.F("unnest", psql.Cast(psql.Arg(pkID), "integer[]")), )) - return Communications.Query(append(mods, - sm.Where(psql.Group(Communications.Columns.ClosedBy).OP("IN", PKArgExpr)), - )...) -} - -// InvalidatedByCommunications starts a query for related objects on communication -func (o *User) InvalidatedByCommunications(mods ...bob.Mod[*dialect.SelectQuery]) CommunicationsQuery { - return Communications.Query(append(mods, - sm.Where(Communications.Columns.InvalidatedBy.EQ(psql.Arg(o.ID))), - )...) -} - -func (os UserSlice) InvalidatedByCommunications(mods ...bob.Mod[*dialect.SelectQuery]) CommunicationsQuery { - 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 Communications.Query(append(mods, - sm.Where(psql.Group(Communications.Columns.InvalidatedBy).OP("IN", PKArgExpr)), - )...) -} - -// OpenedByCommunications starts a query for related objects on communication -func (o *User) OpenedByCommunications(mods ...bob.Mod[*dialect.SelectQuery]) CommunicationsQuery { - return Communications.Query(append(mods, - sm.Where(Communications.Columns.OpenedBy.EQ(psql.Arg(o.ID))), - )...) -} - -func (os UserSlice) OpenedByCommunications(mods ...bob.Mod[*dialect.SelectQuery]) CommunicationsQuery { - 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 Communications.Query(append(mods, - sm.Where(psql.Group(Communications.Columns.OpenedBy).OP("IN", PKArgExpr)), - )...) -} - -// SetPendingByCommunications starts a query for related objects on communication -func (o *User) SetPendingByCommunications(mods ...bob.Mod[*dialect.SelectQuery]) CommunicationsQuery { - return Communications.Query(append(mods, - sm.Where(Communications.Columns.SetPendingBy.EQ(psql.Arg(o.ID))), - )...) -} - -func (os UserSlice) SetPendingByCommunications(mods ...bob.Mod[*dialect.SelectQuery]) CommunicationsQuery { - 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 Communications.Query(append(mods, - sm.Where(psql.Group(Communications.Columns.SetPendingBy).OP("IN", PKArgExpr)), - )...) -} - -// SetPossibleIssueByCommunications starts a query for related objects on communication -func (o *User) SetPossibleIssueByCommunications(mods ...bob.Mod[*dialect.SelectQuery]) CommunicationsQuery { - return Communications.Query(append(mods, - sm.Where(Communications.Columns.SetPossibleIssueBy.EQ(psql.Arg(o.ID))), - )...) -} - -func (os UserSlice) SetPossibleIssueByCommunications(mods ...bob.Mod[*dialect.SelectQuery]) CommunicationsQuery { - 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 Communications.Query(append(mods, - sm.Where(psql.Group(Communications.Columns.SetPossibleIssueBy).OP("IN", PKArgExpr)), - )...) -} - -// SetPossibleResolvedByCommunications starts a query for related objects on communication -func (o *User) SetPossibleResolvedByCommunications(mods ...bob.Mod[*dialect.SelectQuery]) CommunicationsQuery { - return Communications.Query(append(mods, - sm.Where(Communications.Columns.SetPossibleResolvedBy.EQ(psql.Arg(o.ID))), - )...) -} - -func (os UserSlice) SetPossibleResolvedByCommunications(mods ...bob.Mod[*dialect.SelectQuery]) CommunicationsQuery { - 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 Communications.Query(append(mods, - sm.Where(psql.Group(Communications.Columns.SetPossibleResolvedBy).OP("IN", PKArgExpr)), + return CommunicationLogEntries.Query(append(mods, + sm.Where(psql.Group(CommunicationLogEntries.Columns.User).OP("IN", PKArgExpr)), )...) } @@ -1584,409 +1459,69 @@ func (user0 *User) AttachCreatorTextJobs(ctx context.Context, exec bob.Executor, return nil } -func insertUserClosedByCommunications0(ctx context.Context, exec bob.Executor, communications1 []*CommunicationSetter, user0 *User) (CommunicationSlice, error) { - for i := range communications1 { - communications1[i].ClosedBy = omitnull.From(user0.ID) +func insertUserCommunicationLogEntries0(ctx context.Context, exec bob.Executor, communicationLogEntries1 []*CommunicationLogEntrySetter, user0 *User) (CommunicationLogEntrySlice, error) { + for i := range communicationLogEntries1 { + communicationLogEntries1[i].User = omitnull.From(user0.ID) } - ret, err := Communications.Insert(bob.ToMods(communications1...)).All(ctx, exec) + ret, err := CommunicationLogEntries.Insert(bob.ToMods(communicationLogEntries1...)).All(ctx, exec) if err != nil { - return ret, fmt.Errorf("insertUserClosedByCommunications0: %w", err) + return ret, fmt.Errorf("insertUserCommunicationLogEntries0: %w", err) } return ret, nil } -func attachUserClosedByCommunications0(ctx context.Context, exec bob.Executor, count int, communications1 CommunicationSlice, user0 *User) (CommunicationSlice, error) { - setter := &CommunicationSetter{ - ClosedBy: omitnull.From(user0.ID), +func attachUserCommunicationLogEntries0(ctx context.Context, exec bob.Executor, count int, communicationLogEntries1 CommunicationLogEntrySlice, user0 *User) (CommunicationLogEntrySlice, error) { + setter := &CommunicationLogEntrySetter{ + User: omitnull.From(user0.ID), } - err := communications1.UpdateAll(ctx, exec, *setter) + err := communicationLogEntries1.UpdateAll(ctx, exec, *setter) if err != nil { - return nil, fmt.Errorf("attachUserClosedByCommunications0: %w", err) + return nil, fmt.Errorf("attachUserCommunicationLogEntries0: %w", err) } - return communications1, nil + return communicationLogEntries1, nil } -func (user0 *User) InsertClosedByCommunications(ctx context.Context, exec bob.Executor, related ...*CommunicationSetter) error { +func (user0 *User) InsertCommunicationLogEntries(ctx context.Context, exec bob.Executor, related ...*CommunicationLogEntrySetter) error { if len(related) == 0 { return nil } var err error - communications1, err := insertUserClosedByCommunications0(ctx, exec, related, user0) + communicationLogEntries1, err := insertUserCommunicationLogEntries0(ctx, exec, related, user0) if err != nil { return err } - user0.R.ClosedByCommunications = append(user0.R.ClosedByCommunications, communications1...) + user0.R.CommunicationLogEntries = append(user0.R.CommunicationLogEntries, communicationLogEntries1...) - for _, rel := range communications1 { - rel.R.ClosedByUser = user0 + for _, rel := range communicationLogEntries1 { + rel.R.User = user0 } return nil } -func (user0 *User) AttachClosedByCommunications(ctx context.Context, exec bob.Executor, related ...*Communication) error { +func (user0 *User) AttachCommunicationLogEntries(ctx context.Context, exec bob.Executor, related ...*CommunicationLogEntry) error { if len(related) == 0 { return nil } var err error - communications1 := CommunicationSlice(related) + communicationLogEntries1 := CommunicationLogEntrySlice(related) - _, err = attachUserClosedByCommunications0(ctx, exec, len(related), communications1, user0) + _, err = attachUserCommunicationLogEntries0(ctx, exec, len(related), communicationLogEntries1, user0) if err != nil { return err } - user0.R.ClosedByCommunications = append(user0.R.ClosedByCommunications, communications1...) + user0.R.CommunicationLogEntries = append(user0.R.CommunicationLogEntries, communicationLogEntries1...) for _, rel := range related { - rel.R.ClosedByUser = user0 - } - - return nil -} - -func insertUserInvalidatedByCommunications0(ctx context.Context, exec bob.Executor, communications1 []*CommunicationSetter, user0 *User) (CommunicationSlice, error) { - for i := range communications1 { - communications1[i].InvalidatedBy = omitnull.From(user0.ID) - } - - ret, err := Communications.Insert(bob.ToMods(communications1...)).All(ctx, exec) - if err != nil { - return ret, fmt.Errorf("insertUserInvalidatedByCommunications0: %w", err) - } - - return ret, nil -} - -func attachUserInvalidatedByCommunications0(ctx context.Context, exec bob.Executor, count int, communications1 CommunicationSlice, user0 *User) (CommunicationSlice, error) { - setter := &CommunicationSetter{ - InvalidatedBy: omitnull.From(user0.ID), - } - - err := communications1.UpdateAll(ctx, exec, *setter) - if err != nil { - return nil, fmt.Errorf("attachUserInvalidatedByCommunications0: %w", err) - } - - return communications1, nil -} - -func (user0 *User) InsertInvalidatedByCommunications(ctx context.Context, exec bob.Executor, related ...*CommunicationSetter) error { - if len(related) == 0 { - return nil - } - - var err error - - communications1, err := insertUserInvalidatedByCommunications0(ctx, exec, related, user0) - if err != nil { - return err - } - - user0.R.InvalidatedByCommunications = append(user0.R.InvalidatedByCommunications, communications1...) - - for _, rel := range communications1 { - rel.R.InvalidatedByUser = user0 - } - return nil -} - -func (user0 *User) AttachInvalidatedByCommunications(ctx context.Context, exec bob.Executor, related ...*Communication) error { - if len(related) == 0 { - return nil - } - - var err error - communications1 := CommunicationSlice(related) - - _, err = attachUserInvalidatedByCommunications0(ctx, exec, len(related), communications1, user0) - if err != nil { - return err - } - - user0.R.InvalidatedByCommunications = append(user0.R.InvalidatedByCommunications, communications1...) - - for _, rel := range related { - rel.R.InvalidatedByUser = user0 - } - - return nil -} - -func insertUserOpenedByCommunications0(ctx context.Context, exec bob.Executor, communications1 []*CommunicationSetter, user0 *User) (CommunicationSlice, error) { - for i := range communications1 { - communications1[i].OpenedBy = omitnull.From(user0.ID) - } - - ret, err := Communications.Insert(bob.ToMods(communications1...)).All(ctx, exec) - if err != nil { - return ret, fmt.Errorf("insertUserOpenedByCommunications0: %w", err) - } - - return ret, nil -} - -func attachUserOpenedByCommunications0(ctx context.Context, exec bob.Executor, count int, communications1 CommunicationSlice, user0 *User) (CommunicationSlice, error) { - setter := &CommunicationSetter{ - OpenedBy: omitnull.From(user0.ID), - } - - err := communications1.UpdateAll(ctx, exec, *setter) - if err != nil { - return nil, fmt.Errorf("attachUserOpenedByCommunications0: %w", err) - } - - return communications1, nil -} - -func (user0 *User) InsertOpenedByCommunications(ctx context.Context, exec bob.Executor, related ...*CommunicationSetter) error { - if len(related) == 0 { - return nil - } - - var err error - - communications1, err := insertUserOpenedByCommunications0(ctx, exec, related, user0) - if err != nil { - return err - } - - user0.R.OpenedByCommunications = append(user0.R.OpenedByCommunications, communications1...) - - for _, rel := range communications1 { - rel.R.OpenedByUser = user0 - } - return nil -} - -func (user0 *User) AttachOpenedByCommunications(ctx context.Context, exec bob.Executor, related ...*Communication) error { - if len(related) == 0 { - return nil - } - - var err error - communications1 := CommunicationSlice(related) - - _, err = attachUserOpenedByCommunications0(ctx, exec, len(related), communications1, user0) - if err != nil { - return err - } - - user0.R.OpenedByCommunications = append(user0.R.OpenedByCommunications, communications1...) - - for _, rel := range related { - rel.R.OpenedByUser = user0 - } - - return nil -} - -func insertUserSetPendingByCommunications0(ctx context.Context, exec bob.Executor, communications1 []*CommunicationSetter, user0 *User) (CommunicationSlice, error) { - for i := range communications1 { - communications1[i].SetPendingBy = omitnull.From(user0.ID) - } - - ret, err := Communications.Insert(bob.ToMods(communications1...)).All(ctx, exec) - if err != nil { - return ret, fmt.Errorf("insertUserSetPendingByCommunications0: %w", err) - } - - return ret, nil -} - -func attachUserSetPendingByCommunications0(ctx context.Context, exec bob.Executor, count int, communications1 CommunicationSlice, user0 *User) (CommunicationSlice, error) { - setter := &CommunicationSetter{ - SetPendingBy: omitnull.From(user0.ID), - } - - err := communications1.UpdateAll(ctx, exec, *setter) - if err != nil { - return nil, fmt.Errorf("attachUserSetPendingByCommunications0: %w", err) - } - - return communications1, nil -} - -func (user0 *User) InsertSetPendingByCommunications(ctx context.Context, exec bob.Executor, related ...*CommunicationSetter) error { - if len(related) == 0 { - return nil - } - - var err error - - communications1, err := insertUserSetPendingByCommunications0(ctx, exec, related, user0) - if err != nil { - return err - } - - user0.R.SetPendingByCommunications = append(user0.R.SetPendingByCommunications, communications1...) - - for _, rel := range communications1 { - rel.R.SetPendingByUser = user0 - } - return nil -} - -func (user0 *User) AttachSetPendingByCommunications(ctx context.Context, exec bob.Executor, related ...*Communication) error { - if len(related) == 0 { - return nil - } - - var err error - communications1 := CommunicationSlice(related) - - _, err = attachUserSetPendingByCommunications0(ctx, exec, len(related), communications1, user0) - if err != nil { - return err - } - - user0.R.SetPendingByCommunications = append(user0.R.SetPendingByCommunications, communications1...) - - for _, rel := range related { - rel.R.SetPendingByUser = user0 - } - - return nil -} - -func insertUserSetPossibleIssueByCommunications0(ctx context.Context, exec bob.Executor, communications1 []*CommunicationSetter, user0 *User) (CommunicationSlice, error) { - for i := range communications1 { - communications1[i].SetPossibleIssueBy = omitnull.From(user0.ID) - } - - ret, err := Communications.Insert(bob.ToMods(communications1...)).All(ctx, exec) - if err != nil { - return ret, fmt.Errorf("insertUserSetPossibleIssueByCommunications0: %w", err) - } - - return ret, nil -} - -func attachUserSetPossibleIssueByCommunications0(ctx context.Context, exec bob.Executor, count int, communications1 CommunicationSlice, user0 *User) (CommunicationSlice, error) { - setter := &CommunicationSetter{ - SetPossibleIssueBy: omitnull.From(user0.ID), - } - - err := communications1.UpdateAll(ctx, exec, *setter) - if err != nil { - return nil, fmt.Errorf("attachUserSetPossibleIssueByCommunications0: %w", err) - } - - return communications1, nil -} - -func (user0 *User) InsertSetPossibleIssueByCommunications(ctx context.Context, exec bob.Executor, related ...*CommunicationSetter) error { - if len(related) == 0 { - return nil - } - - var err error - - communications1, err := insertUserSetPossibleIssueByCommunications0(ctx, exec, related, user0) - if err != nil { - return err - } - - user0.R.SetPossibleIssueByCommunications = append(user0.R.SetPossibleIssueByCommunications, communications1...) - - for _, rel := range communications1 { - rel.R.SetPossibleIssueByUser = user0 - } - return nil -} - -func (user0 *User) AttachSetPossibleIssueByCommunications(ctx context.Context, exec bob.Executor, related ...*Communication) error { - if len(related) == 0 { - return nil - } - - var err error - communications1 := CommunicationSlice(related) - - _, err = attachUserSetPossibleIssueByCommunications0(ctx, exec, len(related), communications1, user0) - if err != nil { - return err - } - - user0.R.SetPossibleIssueByCommunications = append(user0.R.SetPossibleIssueByCommunications, communications1...) - - for _, rel := range related { - rel.R.SetPossibleIssueByUser = user0 - } - - return nil -} - -func insertUserSetPossibleResolvedByCommunications0(ctx context.Context, exec bob.Executor, communications1 []*CommunicationSetter, user0 *User) (CommunicationSlice, error) { - for i := range communications1 { - communications1[i].SetPossibleResolvedBy = omitnull.From(user0.ID) - } - - ret, err := Communications.Insert(bob.ToMods(communications1...)).All(ctx, exec) - if err != nil { - return ret, fmt.Errorf("insertUserSetPossibleResolvedByCommunications0: %w", err) - } - - return ret, nil -} - -func attachUserSetPossibleResolvedByCommunications0(ctx context.Context, exec bob.Executor, count int, communications1 CommunicationSlice, user0 *User) (CommunicationSlice, error) { - setter := &CommunicationSetter{ - SetPossibleResolvedBy: omitnull.From(user0.ID), - } - - err := communications1.UpdateAll(ctx, exec, *setter) - if err != nil { - return nil, fmt.Errorf("attachUserSetPossibleResolvedByCommunications0: %w", err) - } - - return communications1, nil -} - -func (user0 *User) InsertSetPossibleResolvedByCommunications(ctx context.Context, exec bob.Executor, related ...*CommunicationSetter) error { - if len(related) == 0 { - return nil - } - - var err error - - communications1, err := insertUserSetPossibleResolvedByCommunications0(ctx, exec, related, user0) - if err != nil { - return err - } - - user0.R.SetPossibleResolvedByCommunications = append(user0.R.SetPossibleResolvedByCommunications, communications1...) - - for _, rel := range communications1 { - rel.R.SetPossibleResolvedByUser = user0 - } - return nil -} - -func (user0 *User) AttachSetPossibleResolvedByCommunications(ctx context.Context, exec bob.Executor, related ...*Communication) error { - if len(related) == 0 { - return nil - } - - var err error - communications1 := CommunicationSlice(related) - - _, err = attachUserSetPossibleResolvedByCommunications0(ctx, exec, len(related), communications1, user0) - if err != nil { - return err - } - - user0.R.SetPossibleResolvedByCommunications = append(user0.R.SetPossibleResolvedByCommunications, communications1...) - - for _, rel := range related { - rel.R.SetPossibleResolvedByUser = user0 + rel.R.User = user0 } return nil @@ -3738,87 +3273,17 @@ func (o *User) Preload(name string, retrieved any) error { } } return nil - case "ClosedByCommunications": - rels, ok := retrieved.(CommunicationSlice) + case "CommunicationLogEntries": + rels, ok := retrieved.(CommunicationLogEntrySlice) if !ok { return fmt.Errorf("user cannot load %T as %q", retrieved, name) } - o.R.ClosedByCommunications = rels + o.R.CommunicationLogEntries = rels for _, rel := range rels { if rel != nil { - rel.R.ClosedByUser = o - } - } - return nil - case "InvalidatedByCommunications": - rels, ok := retrieved.(CommunicationSlice) - if !ok { - return fmt.Errorf("user cannot load %T as %q", retrieved, name) - } - - o.R.InvalidatedByCommunications = rels - - for _, rel := range rels { - if rel != nil { - rel.R.InvalidatedByUser = o - } - } - return nil - case "OpenedByCommunications": - rels, ok := retrieved.(CommunicationSlice) - if !ok { - return fmt.Errorf("user cannot load %T as %q", retrieved, name) - } - - o.R.OpenedByCommunications = rels - - for _, rel := range rels { - if rel != nil { - rel.R.OpenedByUser = o - } - } - return nil - case "SetPendingByCommunications": - rels, ok := retrieved.(CommunicationSlice) - if !ok { - return fmt.Errorf("user cannot load %T as %q", retrieved, name) - } - - o.R.SetPendingByCommunications = rels - - for _, rel := range rels { - if rel != nil { - rel.R.SetPendingByUser = o - } - } - return nil - case "SetPossibleIssueByCommunications": - rels, ok := retrieved.(CommunicationSlice) - if !ok { - return fmt.Errorf("user cannot load %T as %q", retrieved, name) - } - - o.R.SetPossibleIssueByCommunications = rels - - for _, rel := range rels { - if rel != nil { - rel.R.SetPossibleIssueByUser = o - } - } - return nil - case "SetPossibleResolvedByCommunications": - rels, ok := retrieved.(CommunicationSlice) - if !ok { - return fmt.Errorf("user cannot load %T as %q", retrieved, name) - } - - o.R.SetPossibleResolvedByCommunications = rels - - for _, rel := range rels { - if rel != nil { - rel.R.SetPossibleResolvedByUser = o + rel.R.User = o } } return nil @@ -4198,61 +3663,41 @@ func buildUserPreloader() userPreloader { } type userThenLoader[Q orm.Loadable] struct { - CreatorTextJobs func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] - ClosedByCommunications func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] - InvalidatedByCommunications func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] - OpenedByCommunications func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] - SetPendingByCommunications func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] - SetPossibleIssueByCommunications func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] - SetPossibleResolvedByCommunications func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] - CreatorComplianceReportRequests func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] - CreatorFeatures func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] - CommitterFiles func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] - CreatorFiles func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] - FileuploadPool func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] - CreatorLeads func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] - ImpersonatorLogImpersonations func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] - TargetLogImpersonations func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] - CreatorNoteAudios func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] - DeletorNoteAudios func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] - CreatorNoteImages func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] - DeletorNoteImages func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] - UserNotifications func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] - ReviewerNuisanceOlds func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] - ReviewerReports func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] - UserReportLogs func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] - ReviewerWaterOlds func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] - CreatorReportTexts func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] - CreatorResidents func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] - CreatorReviewTasks func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] - ReviewerReviewTasks func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] - AddressorSignals func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] - CreatorSignals func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] - CreatorSites func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] - Organization func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] + CreatorTextJobs func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] + CommunicationLogEntries func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] + CreatorComplianceReportRequests func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] + CreatorFeatures func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] + CommitterFiles func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] + CreatorFiles func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] + FileuploadPool func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] + CreatorLeads func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] + ImpersonatorLogImpersonations func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] + TargetLogImpersonations func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] + CreatorNoteAudios func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] + DeletorNoteAudios func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] + CreatorNoteImages func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] + DeletorNoteImages func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] + UserNotifications func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] + ReviewerNuisanceOlds func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] + ReviewerReports func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] + UserReportLogs func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] + ReviewerWaterOlds func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] + CreatorReportTexts func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] + CreatorResidents func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] + CreatorReviewTasks func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] + ReviewerReviewTasks func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] + AddressorSignals func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] + CreatorSignals func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] + CreatorSites func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] + Organization func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] } func buildUserThenLoader[Q orm.Loadable]() userThenLoader[Q] { type CreatorTextJobsLoadInterface interface { LoadCreatorTextJobs(context.Context, bob.Executor, ...bob.Mod[*dialect.SelectQuery]) error } - type ClosedByCommunicationsLoadInterface interface { - LoadClosedByCommunications(context.Context, bob.Executor, ...bob.Mod[*dialect.SelectQuery]) error - } - type InvalidatedByCommunicationsLoadInterface interface { - LoadInvalidatedByCommunications(context.Context, bob.Executor, ...bob.Mod[*dialect.SelectQuery]) error - } - type OpenedByCommunicationsLoadInterface interface { - LoadOpenedByCommunications(context.Context, bob.Executor, ...bob.Mod[*dialect.SelectQuery]) error - } - type SetPendingByCommunicationsLoadInterface interface { - LoadSetPendingByCommunications(context.Context, bob.Executor, ...bob.Mod[*dialect.SelectQuery]) error - } - type SetPossibleIssueByCommunicationsLoadInterface interface { - LoadSetPossibleIssueByCommunications(context.Context, bob.Executor, ...bob.Mod[*dialect.SelectQuery]) error - } - type SetPossibleResolvedByCommunicationsLoadInterface interface { - LoadSetPossibleResolvedByCommunications(context.Context, bob.Executor, ...bob.Mod[*dialect.SelectQuery]) error + type CommunicationLogEntriesLoadInterface interface { + LoadCommunicationLogEntries(context.Context, bob.Executor, ...bob.Mod[*dialect.SelectQuery]) error } type CreatorComplianceReportRequestsLoadInterface interface { LoadCreatorComplianceReportRequests(context.Context, bob.Executor, ...bob.Mod[*dialect.SelectQuery]) error @@ -4337,40 +3782,10 @@ func buildUserThenLoader[Q orm.Loadable]() userThenLoader[Q] { return retrieved.LoadCreatorTextJobs(ctx, exec, mods...) }, ), - ClosedByCommunications: thenLoadBuilder[Q]( - "ClosedByCommunications", - func(ctx context.Context, exec bob.Executor, retrieved ClosedByCommunicationsLoadInterface, mods ...bob.Mod[*dialect.SelectQuery]) error { - return retrieved.LoadClosedByCommunications(ctx, exec, mods...) - }, - ), - InvalidatedByCommunications: thenLoadBuilder[Q]( - "InvalidatedByCommunications", - func(ctx context.Context, exec bob.Executor, retrieved InvalidatedByCommunicationsLoadInterface, mods ...bob.Mod[*dialect.SelectQuery]) error { - return retrieved.LoadInvalidatedByCommunications(ctx, exec, mods...) - }, - ), - OpenedByCommunications: thenLoadBuilder[Q]( - "OpenedByCommunications", - func(ctx context.Context, exec bob.Executor, retrieved OpenedByCommunicationsLoadInterface, mods ...bob.Mod[*dialect.SelectQuery]) error { - return retrieved.LoadOpenedByCommunications(ctx, exec, mods...) - }, - ), - SetPendingByCommunications: thenLoadBuilder[Q]( - "SetPendingByCommunications", - func(ctx context.Context, exec bob.Executor, retrieved SetPendingByCommunicationsLoadInterface, mods ...bob.Mod[*dialect.SelectQuery]) error { - return retrieved.LoadSetPendingByCommunications(ctx, exec, mods...) - }, - ), - SetPossibleIssueByCommunications: thenLoadBuilder[Q]( - "SetPossibleIssueByCommunications", - func(ctx context.Context, exec bob.Executor, retrieved SetPossibleIssueByCommunicationsLoadInterface, mods ...bob.Mod[*dialect.SelectQuery]) error { - return retrieved.LoadSetPossibleIssueByCommunications(ctx, exec, mods...) - }, - ), - SetPossibleResolvedByCommunications: thenLoadBuilder[Q]( - "SetPossibleResolvedByCommunications", - func(ctx context.Context, exec bob.Executor, retrieved SetPossibleResolvedByCommunicationsLoadInterface, mods ...bob.Mod[*dialect.SelectQuery]) error { - return retrieved.LoadSetPossibleResolvedByCommunications(ctx, exec, mods...) + CommunicationLogEntries: thenLoadBuilder[Q]( + "CommunicationLogEntries", + func(ctx context.Context, exec bob.Executor, retrieved CommunicationLogEntriesLoadInterface, mods ...bob.Mod[*dialect.SelectQuery]) error { + return retrieved.LoadCommunicationLogEntries(ctx, exec, mods...) }, ), CreatorComplianceReportRequests: thenLoadBuilder[Q]( @@ -4590,35 +4005,35 @@ func (os UserSlice) LoadCreatorTextJobs(ctx context.Context, exec bob.Executor, return nil } -// LoadClosedByCommunications loads the user's ClosedByCommunications into the .R struct -func (o *User) LoadClosedByCommunications(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error { +// LoadCommunicationLogEntries loads the user's CommunicationLogEntries into the .R struct +func (o *User) LoadCommunicationLogEntries(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error { if o == nil { return nil } // Reset the relationship - o.R.ClosedByCommunications = nil + o.R.CommunicationLogEntries = nil - related, err := o.ClosedByCommunications(mods...).All(ctx, exec) + related, err := o.CommunicationLogEntries(mods...).All(ctx, exec) if err != nil { return err } for _, rel := range related { - rel.R.ClosedByUser = o + rel.R.User = o } - o.R.ClosedByCommunications = related + o.R.CommunicationLogEntries = related return nil } -// LoadClosedByCommunications loads the user's ClosedByCommunications into the .R struct -func (os UserSlice) LoadClosedByCommunications(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error { +// LoadCommunicationLogEntries loads the user's CommunicationLogEntries into the .R struct +func (os UserSlice) LoadCommunicationLogEntries(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error { if len(os) == 0 { return nil } - communications, err := os.ClosedByCommunications(mods...).All(ctx, exec) + communicationLogEntries, err := os.CommunicationLogEntries(mods...).All(ctx, exec) if err != nil { return err } @@ -4628,7 +4043,7 @@ func (os UserSlice) LoadClosedByCommunications(ctx context.Context, exec bob.Exe continue } - o.R.ClosedByCommunications = nil + o.R.CommunicationLogEntries = nil } for _, o := range os { @@ -4636,338 +4051,18 @@ func (os UserSlice) LoadClosedByCommunications(ctx context.Context, exec bob.Exe continue } - for _, rel := range communications { + for _, rel := range communicationLogEntries { - if !rel.ClosedBy.IsValue() { + if !rel.User.IsValue() { continue } - if !(rel.ClosedBy.IsValue() && o.ID == rel.ClosedBy.MustGet()) { + if !(rel.User.IsValue() && o.ID == rel.User.MustGet()) { continue } - rel.R.ClosedByUser = o + rel.R.User = o - o.R.ClosedByCommunications = append(o.R.ClosedByCommunications, rel) - } - } - - return nil -} - -// LoadInvalidatedByCommunications loads the user's InvalidatedByCommunications into the .R struct -func (o *User) LoadInvalidatedByCommunications(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error { - if o == nil { - return nil - } - - // Reset the relationship - o.R.InvalidatedByCommunications = nil - - related, err := o.InvalidatedByCommunications(mods...).All(ctx, exec) - if err != nil { - return err - } - - for _, rel := range related { - rel.R.InvalidatedByUser = o - } - - o.R.InvalidatedByCommunications = related - return nil -} - -// LoadInvalidatedByCommunications loads the user's InvalidatedByCommunications into the .R struct -func (os UserSlice) LoadInvalidatedByCommunications(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error { - if len(os) == 0 { - return nil - } - - communications, err := os.InvalidatedByCommunications(mods...).All(ctx, exec) - if err != nil { - return err - } - - for _, o := range os { - if o == nil { - continue - } - - o.R.InvalidatedByCommunications = nil - } - - for _, o := range os { - if o == nil { - continue - } - - for _, rel := range communications { - - if !rel.InvalidatedBy.IsValue() { - continue - } - if !(rel.InvalidatedBy.IsValue() && o.ID == rel.InvalidatedBy.MustGet()) { - continue - } - - rel.R.InvalidatedByUser = o - - o.R.InvalidatedByCommunications = append(o.R.InvalidatedByCommunications, rel) - } - } - - return nil -} - -// LoadOpenedByCommunications loads the user's OpenedByCommunications into the .R struct -func (o *User) LoadOpenedByCommunications(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error { - if o == nil { - return nil - } - - // Reset the relationship - o.R.OpenedByCommunications = nil - - related, err := o.OpenedByCommunications(mods...).All(ctx, exec) - if err != nil { - return err - } - - for _, rel := range related { - rel.R.OpenedByUser = o - } - - o.R.OpenedByCommunications = related - return nil -} - -// LoadOpenedByCommunications loads the user's OpenedByCommunications into the .R struct -func (os UserSlice) LoadOpenedByCommunications(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error { - if len(os) == 0 { - return nil - } - - communications, err := os.OpenedByCommunications(mods...).All(ctx, exec) - if err != nil { - return err - } - - for _, o := range os { - if o == nil { - continue - } - - o.R.OpenedByCommunications = nil - } - - for _, o := range os { - if o == nil { - continue - } - - for _, rel := range communications { - - if !rel.OpenedBy.IsValue() { - continue - } - if !(rel.OpenedBy.IsValue() && o.ID == rel.OpenedBy.MustGet()) { - continue - } - - rel.R.OpenedByUser = o - - o.R.OpenedByCommunications = append(o.R.OpenedByCommunications, rel) - } - } - - return nil -} - -// LoadSetPendingByCommunications loads the user's SetPendingByCommunications into the .R struct -func (o *User) LoadSetPendingByCommunications(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error { - if o == nil { - return nil - } - - // Reset the relationship - o.R.SetPendingByCommunications = nil - - related, err := o.SetPendingByCommunications(mods...).All(ctx, exec) - if err != nil { - return err - } - - for _, rel := range related { - rel.R.SetPendingByUser = o - } - - o.R.SetPendingByCommunications = related - return nil -} - -// LoadSetPendingByCommunications loads the user's SetPendingByCommunications into the .R struct -func (os UserSlice) LoadSetPendingByCommunications(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error { - if len(os) == 0 { - return nil - } - - communications, err := os.SetPendingByCommunications(mods...).All(ctx, exec) - if err != nil { - return err - } - - for _, o := range os { - if o == nil { - continue - } - - o.R.SetPendingByCommunications = nil - } - - for _, o := range os { - if o == nil { - continue - } - - for _, rel := range communications { - - if !rel.SetPendingBy.IsValue() { - continue - } - if !(rel.SetPendingBy.IsValue() && o.ID == rel.SetPendingBy.MustGet()) { - continue - } - - rel.R.SetPendingByUser = o - - o.R.SetPendingByCommunications = append(o.R.SetPendingByCommunications, rel) - } - } - - return nil -} - -// LoadSetPossibleIssueByCommunications loads the user's SetPossibleIssueByCommunications into the .R struct -func (o *User) LoadSetPossibleIssueByCommunications(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error { - if o == nil { - return nil - } - - // Reset the relationship - o.R.SetPossibleIssueByCommunications = nil - - related, err := o.SetPossibleIssueByCommunications(mods...).All(ctx, exec) - if err != nil { - return err - } - - for _, rel := range related { - rel.R.SetPossibleIssueByUser = o - } - - o.R.SetPossibleIssueByCommunications = related - return nil -} - -// LoadSetPossibleIssueByCommunications loads the user's SetPossibleIssueByCommunications into the .R struct -func (os UserSlice) LoadSetPossibleIssueByCommunications(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error { - if len(os) == 0 { - return nil - } - - communications, err := os.SetPossibleIssueByCommunications(mods...).All(ctx, exec) - if err != nil { - return err - } - - for _, o := range os { - if o == nil { - continue - } - - o.R.SetPossibleIssueByCommunications = nil - } - - for _, o := range os { - if o == nil { - continue - } - - for _, rel := range communications { - - if !rel.SetPossibleIssueBy.IsValue() { - continue - } - if !(rel.SetPossibleIssueBy.IsValue() && o.ID == rel.SetPossibleIssueBy.MustGet()) { - continue - } - - rel.R.SetPossibleIssueByUser = o - - o.R.SetPossibleIssueByCommunications = append(o.R.SetPossibleIssueByCommunications, rel) - } - } - - return nil -} - -// LoadSetPossibleResolvedByCommunications loads the user's SetPossibleResolvedByCommunications into the .R struct -func (o *User) LoadSetPossibleResolvedByCommunications(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error { - if o == nil { - return nil - } - - // Reset the relationship - o.R.SetPossibleResolvedByCommunications = nil - - related, err := o.SetPossibleResolvedByCommunications(mods...).All(ctx, exec) - if err != nil { - return err - } - - for _, rel := range related { - rel.R.SetPossibleResolvedByUser = o - } - - o.R.SetPossibleResolvedByCommunications = related - return nil -} - -// LoadSetPossibleResolvedByCommunications loads the user's SetPossibleResolvedByCommunications into the .R struct -func (os UserSlice) LoadSetPossibleResolvedByCommunications(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error { - if len(os) == 0 { - return nil - } - - communications, err := os.SetPossibleResolvedByCommunications(mods...).All(ctx, exec) - if err != nil { - return err - } - - for _, o := range os { - if o == nil { - continue - } - - o.R.SetPossibleResolvedByCommunications = nil - } - - for _, o := range os { - if o == nil { - continue - } - - for _, rel := range communications { - - if !rel.SetPossibleResolvedBy.IsValue() { - continue - } - if !(rel.SetPossibleResolvedBy.IsValue() && o.ID == rel.SetPossibleResolvedBy.MustGet()) { - continue - } - - rel.R.SetPossibleResolvedByUser = o - - o.R.SetPossibleResolvedByCommunications = append(o.R.SetPossibleResolvedByCommunications, rel) + o.R.CommunicationLogEntries = append(o.R.CommunicationLogEntries, rel) } } diff --git a/db/query/arcgis/account.go b/db/query/arcgis/account.go index 2a6b5428..6f1b9b49 100644 --- a/db/query/arcgis/account.go +++ b/db/query/arcgis/account.go @@ -10,14 +10,14 @@ import ( "github.com/go-jet/jet/v2/postgres" ) -func AccountFromID(ctx context.Context, org_id string) (*model.Account, error) { +func AccountFromID(ctx context.Context, org_id string) (model.Account, error) { statement := table.Account.SELECT( table.Account.AllColumns, ).FROM(table.Account). WHERE(table.Account.ID.EQ(postgres.String(org_id))) return db.ExecuteOne[model.Account](ctx, statement) } -func AccountInsert(ctx context.Context, txn bob.Tx, m *model.Account) (*model.Account, error) { +func AccountInsert(ctx context.Context, txn bob.Tx, m *model.Account) (model.Account, error) { statement := table.Account.INSERT(table.Account.AllColumns). MODEL(m) return db.ExecuteOneTxBob[model.Account](ctx, txn, statement) diff --git a/db/query/arcgis/oauth.go b/db/query/arcgis/oauth.go index f283cc2b..cb65b9eb 100644 --- a/db/query/arcgis/oauth.go +++ b/db/query/arcgis/oauth.go @@ -10,7 +10,7 @@ import ( "github.com/go-jet/jet/v2/postgres" ) -func OAuthTokenInsert(ctx context.Context, m *model.OAuthToken) (*model.OAuthToken, error) { +func OAuthTokenInsert(ctx context.Context, m *model.OAuthToken) (model.OAuthToken, error) { statement := table.OAuthToken.INSERT(table.OAuthToken.MutableColumns). MODEL(m) return db.ExecuteOne[model.OAuthToken](ctx, statement) @@ -21,20 +21,20 @@ func OAuthTokenInvalidate(ctx context.Context, id int64) error { WHERE(table.OAuthToken.ID.EQ(postgres.Int(id))) return db.ExecuteNone(ctx, statement) } -func OAuthTokensValid(ctx context.Context) ([]*model.OAuthToken, error) { +func OAuthTokensValid(ctx context.Context) ([]model.OAuthToken, error) { statement := table.OAuthToken.SELECT(table.OAuthToken.AllColumns). FROM(table.OAuthToken). WHERE(table.OAuthToken.InvalidatedAt.IS_NULL()) return db.ExecuteMany[model.OAuthToken](ctx, statement) } -func OAuthTokenFromID(ctx context.Context, id int64) (*model.OAuthToken, error) { +func OAuthTokenFromID(ctx context.Context, id int64) (model.OAuthToken, error) { statement := table.OAuthToken.SELECT( table.OAuthToken.AllColumns, ).FROM(table.OAuthToken). WHERE(table.OAuthToken.ID.EQ(postgres.Int(id))) return db.ExecuteOne[model.OAuthToken](ctx, statement) } -func OAuthTokenForUser(ctx context.Context, user_id int64) (*model.OAuthToken, error) { +func OAuthTokenForUser(ctx context.Context, user_id int64) (model.OAuthToken, error) { statement := table.OAuthToken.SELECT(table.OAuthToken.AllColumns). FROM(table.OAuthToken). WHERE(table.OAuthToken.InvalidatedAt.IS_NULL().AND( @@ -44,7 +44,7 @@ func OAuthTokenForUser(ctx context.Context, user_id int64) (*model.OAuthToken, e LIMIT(1) return db.ExecuteOne[model.OAuthToken](ctx, statement) } -func OAuthTokensForUser(ctx context.Context, user_id int64) ([]*model.OAuthToken, error) { +func OAuthTokensForUser(ctx context.Context, user_id int64) ([]model.OAuthToken, error) { statement := table.OAuthToken.SELECT(table.OAuthToken.AllColumns). FROM(table.OAuthToken). WHERE(table.OAuthToken.InvalidatedAt.IS_NULL().AND( @@ -52,14 +52,14 @@ func OAuthTokensForUser(ctx context.Context, user_id int64) ([]*model.OAuthToken )) return db.ExecuteMany[model.OAuthToken](ctx, statement) } -func OAuthTokenForUserExists(ctx context.Context, user_id int64) (*bool, error) { +func OAuthTokenForUserExists(ctx context.Context, user_id int64) (bool, error) { statement := table.OAuthToken.SELECT(postgres.Bool(true)). FROM(table.OAuthToken). WHERE(table.OAuthToken.UserID.EQ(postgres.Int(user_id))). LIMIT(1) return db.ExecuteOne[bool](ctx, statement) } -func OAuthTokenUpdateAccessToken(ctx context.Context, oauth_id int64, updates *model.OAuthToken) error { +func OAuthTokenUpdateAccessToken(ctx context.Context, oauth_id int64, updates model.OAuthToken) error { statement := table.OAuthToken.UPDATE( table.OAuthToken.AccessToken, table.OAuthToken.AccessTokenExpires, @@ -68,7 +68,7 @@ func OAuthTokenUpdateAccessToken(ctx context.Context, oauth_id int64, updates *m WHERE(table.OAuthToken.ID.EQ(postgres.Int(oauth_id))) return db.ExecuteNone(ctx, statement) } -func OAuthTokenUpdateRefreshToken(ctx context.Context, oauth_id int64, updates *model.OAuthToken) error { +func OAuthTokenUpdateRefreshToken(ctx context.Context, oauth_id int64, updates model.OAuthToken) error { statement := table.OAuthToken.UPDATE( table.OAuthToken.RefreshToken, table.OAuthToken.RefreshTokenExpires, @@ -78,7 +78,7 @@ func OAuthTokenUpdateRefreshToken(ctx context.Context, oauth_id int64, updates * return db.ExecuteNone(ctx, statement) } -func OAuthTokenUpdateLicense(ctx context.Context, refresh_token string, updates *model.OAuthToken) error { +func OAuthTokenUpdateLicense(ctx context.Context, refresh_token string, updates model.OAuthToken) error { statement := table.OAuthToken.UPDATE( table.OAuthToken.ArcgisID, table.OAuthToken.ArcgisLicenseTypeID, diff --git a/db/query/arcgis/service_feature.go b/db/query/arcgis/service_feature.go index 17359c3d..bb4950ab 100644 --- a/db/query/arcgis/service_feature.go +++ b/db/query/arcgis/service_feature.go @@ -10,21 +10,21 @@ import ( "github.com/go-jet/jet/v2/postgres" ) -func ServiceFeatureFromID(ctx context.Context, id string) (*model.ServiceFeature, error) { +func ServiceFeatureFromID(ctx context.Context, id string) (model.ServiceFeature, error) { statement := table.ServiceFeature.SELECT( table.ServiceFeature.AllColumns, ).FROM(table.ServiceFeature). WHERE(table.ServiceFeature.ItemID.EQ(postgres.String(id))) return db.ExecuteOne[model.ServiceFeature](ctx, statement) } -func ServiceFeatureFromURL(ctx context.Context, url string) (*model.ServiceFeature, error) { +func ServiceFeatureFromURL(ctx context.Context, url string) (model.ServiceFeature, error) { statement := table.ServiceFeature.SELECT( table.ServiceFeature.AllColumns, ).FROM(table.ServiceFeature). WHERE(table.ServiceFeature.URL.EQ(postgres.String(url))) return db.ExecuteOne[model.ServiceFeature](ctx, statement) } -func ServiceFeatureInsert(ctx context.Context, txn bob.Tx, m *model.ServiceFeature) error { +func ServiceFeatureInsert(ctx context.Context, txn bob.Tx, m model.ServiceFeature) error { statement := table.ServiceMap.INSERT(table.ServiceMap.MutableColumns). MODEL(m) return db.ExecuteNoneTxBob(ctx, txn, statement) diff --git a/db/query/arcgis/service_map.go b/db/query/arcgis/service_map.go index 9d25f9c1..29c8701f 100644 --- a/db/query/arcgis/service_map.go +++ b/db/query/arcgis/service_map.go @@ -10,14 +10,14 @@ import ( "github.com/go-jet/jet/v2/postgres" ) -func ServiceMapFromID(ctx context.Context, id string) (*model.ServiceMap, error) { +func ServiceMapFromID(ctx context.Context, id string) (model.ServiceMap, error) { statement := table.ServiceMap.SELECT( table.ServiceMap.AllColumns, ).FROM(table.ServiceMap). WHERE(table.ServiceMap.ArcgisID.EQ(postgres.String(id))) return db.ExecuteOne[model.ServiceMap](ctx, statement) } -func ServiceMapsFromAccountID(ctx context.Context, account_id string) ([]*model.ServiceMap, error) { +func ServiceMapsFromAccountID(ctx context.Context, account_id string) ([]model.ServiceMap, error) { statement := table.ServiceMap.SELECT( table.ServiceMap.AllColumns, ).FROM(table.ServiceMap). diff --git a/db/query/arcgis/user.go b/db/query/arcgis/user.go index 5452285b..ede1d25c 100644 --- a/db/query/arcgis/user.go +++ b/db/query/arcgis/user.go @@ -10,13 +10,13 @@ import ( "github.com/go-jet/jet/v2/postgres" ) -func UserFromID(ctx context.Context, id string) (*model.User, error) { +func UserFromID(ctx context.Context, id string) (model.User, error) { statement := table.User.SELECT(table.User.AllColumns). FROM(table.User). WHERE(table.User.ID.EQ(postgres.String(id))) return db.ExecuteOne[model.User](ctx, statement) } -func UserInsert(ctx context.Context, txn bob.Tx, m *model.User) (*model.User, error) { +func UserInsert(ctx context.Context, txn bob.Tx, m *model.User) (model.User, error) { statement := table.User.INSERT(table.User.MutableColumns). MODEL(m). RETURNING(table.User.AllColumns) diff --git a/db/query/public/address.go b/db/query/public/address.go new file mode 100644 index 00000000..25952b52 --- /dev/null +++ b/db/query/public/address.go @@ -0,0 +1,69 @@ +package public + +import ( + "context" + "errors" + "fmt" + + //"github.com/Gleipnir-Technology/bob" + "github.com/Gleipnir-Technology/nidus-sync/db" + //"github.com/Gleipnir-Technology/nidus-sync/db/gen/nidus-sync/public/enum" + "github.com/Gleipnir-Technology/nidus-sync/db/gen/nidus-sync/public/model" + "github.com/Gleipnir-Technology/nidus-sync/db/gen/nidus-sync/public/table" + "github.com/go-jet/jet/v2/postgres" +) + +func AddressFromGID(ctx context.Context, txn db.Ex, gid string) (*model.Address, error) { + statement := table.Address.SELECT( + table.Address.AllColumns, + ).FROM(table.Address). + WHERE(table.Address.Gid.EQ(postgres.String(gid))) + result, err := db.ExecuteOneTx[model.Address](ctx, txn, statement) + if err != nil { + if errors.Is(err, db.ErrNoRows) { + return nil, nil + } + return nil, fmt.Errorf("execute one: %w", err) + } + return &result, nil +} +func AddressFromID(ctx context.Context, txn db.Ex, comm_id int64) (model.Address, error) { + statement := table.Address.SELECT( + table.Address.AllColumns, + ).FROM(table.Address). + WHERE(table.Address.ID.EQ(postgres.Int(comm_id))) + return db.ExecuteOne[model.Address](ctx, statement) +} +func AddressesFromIDs(ctx context.Context, txn db.Ex, address_ids []int64) ([]model.Address, error) { + sql_ids := make([]postgres.Expression, len(address_ids)) + for i, address_id := range address_ids { + sql_ids[i] = postgres.Int(address_id) + } + statement := table.Address.SELECT( + table.Address.AllColumns, + ).FROM(table.Address). + WHERE(table.Address.ID.IN(sql_ids...)) + return db.ExecuteManyTx[model.Address](ctx, txn, statement) +} +func AddressInsert(ctx context.Context, txn db.Ex, a model.Address) (model.Address, error) { + statement := table.Address. + INSERT(table.Address.MutableColumns). + MODEL(a). + RETURNING(table.Address.AllColumns) + return db.ExecuteOneTx[model.Address](ctx, txn, statement) +} +func AddressInserts(ctx context.Context, txn db.Ex, addresses []model.Address) ([]model.Address, error) { + statement := table.Address. + INSERT(table.Address.MutableColumns). + MODELS(addresses). + RETURNING(table.Address.AllColumns) + return db.ExecuteManyTx[model.Address](ctx, txn, statement) +} + +func addressQuery() postgres.InsertStatement { + return table.Address.INSERT( + table.Address.MutableColumns, + ) + //im.Into("address", "country", "created", "gid", "h3cell", "id", "locality", "location", "number_", "postal_code", "region", "street", "unit"), + //im.Returning("id"), +} diff --git a/db/query/public/communication.go b/db/query/public/communication.go index 2aa13be3..da24532b 100644 --- a/db/query/public/communication.go +++ b/db/query/public/communication.go @@ -2,71 +2,39 @@ package public import ( "context" - "time" - "github.com/Gleipnir-Technology/bob" + //"github.com/Gleipnir-Technology/bob" "github.com/Gleipnir-Technology/nidus-sync/db" + //"github.com/Gleipnir-Technology/nidus-sync/db/gen/nidus-sync/public/enum" "github.com/Gleipnir-Technology/nidus-sync/db/gen/nidus-sync/public/model" "github.com/Gleipnir-Technology/nidus-sync/db/gen/nidus-sync/public/table" "github.com/go-jet/jet/v2/postgres" ) -func CommunicationInsert(ctx context.Context, txn bob.Tx, m *model.Communication) (*model.Communication, error) { - m.Created = time.Now() +func CommunicationInsert(ctx context.Context, txn db.Tx, m model.Communication) (model.Communication, error) { statement := table.Communication.INSERT(table.Communication.MutableColumns). MODEL(m). RETURNING(table.Communication.AllColumns) return db.ExecuteOne[model.Communication](ctx, statement) } -func CommunicationFromID(ctx context.Context, comm_id int64) (*model.Communication, error) { +func CommunicationFromID(ctx context.Context, comm_id int64) (model.Communication, error) { statement := table.Communication.SELECT( table.Communication.AllColumns, ).FROM(table.Communication). WHERE(table.Communication.ID.EQ(postgres.Int(comm_id))) return db.ExecuteOne[model.Communication](ctx, statement) } -func CommunicationsFromOrganization(ctx context.Context, org_id int64) ([]*model.Communication, error) { +func CommunicationsFromOrganization(ctx context.Context, org_id int64) ([]model.Communication, error) { statement := table.Communication.SELECT( table.Communication.AllColumns, ).FROM(table.Communication). WHERE(table.Communication.OrganizationID.EQ(postgres.Int(org_id))) return db.ExecuteMany[model.Communication](ctx, statement) } -func CommunicationMarkInvalid(ctx context.Context, txn db.Tx, org_id int64, user_id int64, comm_id int64) error { +func CommunicationSetStatus(ctx context.Context, txn db.Tx, org_id int64, comm_id int64, status model.Communicationstatus) error { statement := table.Communication.UPDATE(). SET( - table.Communication.Invalidated.SET(postgres.TimestampT(time.Now())), - table.Communication.InvalidatedBy.SET(postgres.Int(user_id)), - ). - WHERE(table.Communication.OrganizationID.EQ(postgres.Int(org_id)).AND( - table.Communication.ID.EQ(postgres.Int(comm_id)))) - return db.ExecuteNoneTx(ctx, txn, statement) -} -func CommunicationMarkPendingResponse(ctx context.Context, txn db.Tx, org_id int64, user_id int64, comm_id int64) error { - statement := table.Communication.UPDATE(). - SET( - table.Communication.SetPending.SET(postgres.TimestampT(time.Now())), - table.Communication.SetPendingBy.SET(postgres.Int(user_id)), - ). - WHERE(table.Communication.OrganizationID.EQ(postgres.Int(org_id)).AND( - table.Communication.ID.EQ(postgres.Int(comm_id)))) - return db.ExecuteNoneTx(ctx, txn, statement) -} -func CommunicationMarkPossibleIssue(ctx context.Context, txn db.Tx, org_id int64, user_id int64, comm_id int64) error { - statement := table.Communication.UPDATE(). - SET( - table.Communication.SetPossibleIssue.SET(postgres.TimestampT(time.Now())), - table.Communication.SetPossibleIssueBy.SET(postgres.Int(user_id)), - ). - WHERE(table.Communication.OrganizationID.EQ(postgres.Int(org_id)).AND( - table.Communication.ID.EQ(postgres.Int(comm_id)))) - return db.ExecuteNoneTx(ctx, txn, statement) -} -func CommunicationMarkPossibleResolved(ctx context.Context, txn db.Tx, org_id int64, user_id int64, comm_id int64) error { - statement := table.Communication.UPDATE(). - SET( - table.Communication.SetPossibleResolved.SET(postgres.TimestampT(time.Now())), - table.Communication.SetPossibleResolvedBy.SET(postgres.Int(user_id)), + table.Communication.Status.SET(postgres.String(status.String())), ). WHERE(table.Communication.OrganizationID.EQ(postgres.Int(org_id)).AND( table.Communication.ID.EQ(postgres.Int(comm_id)))) diff --git a/db/query/public/communication_log_entry.go b/db/query/public/communication_log_entry.go new file mode 100644 index 00000000..7ed2e5f2 --- /dev/null +++ b/db/query/public/communication_log_entry.go @@ -0,0 +1,19 @@ +package public + +import ( + "context" + "time" + + "github.com/Gleipnir-Technology/nidus-sync/db" + "github.com/Gleipnir-Technology/nidus-sync/db/gen/nidus-sync/public/model" + "github.com/Gleipnir-Technology/nidus-sync/db/gen/nidus-sync/public/table" + //"github.com/go-jet/jet/v2/postgres" +) + +func CommunicationLogEntryInsert(ctx context.Context, txn db.Tx, m model.CommunicationLogEntry) (model.CommunicationLogEntry, error) { + m.Created = time.Now() + statement := table.Communication.INSERT(table.Communication.MutableColumns). + MODEL(m). + RETURNING(table.Communication.AllColumns) + return db.ExecuteOne[model.CommunicationLogEntry](ctx, statement) +} diff --git a/db/query/public/signal.go b/db/query/public/signal.go new file mode 100644 index 00000000..9beaf44b --- /dev/null +++ b/db/query/public/signal.go @@ -0,0 +1,19 @@ +package public + +import ( + "context" + + //"github.com/Gleipnir-Technology/bob" + "github.com/Gleipnir-Technology/nidus-sync/db" + //"github.com/Gleipnir-Technology/nidus-sync/db/gen/nidus-sync/public/enum" + "github.com/Gleipnir-Technology/nidus-sync/db/gen/nidus-sync/public/model" + "github.com/Gleipnir-Technology/nidus-sync/db/gen/nidus-sync/public/table" + //"github.com/go-jet/jet/v2/postgres" +) + +func SignalInsert(ctx context.Context, txn db.Tx, m model.Signal) (model.Signal, error) { + statement := table.Signal.INSERT(table.Signal.MutableColumns). + MODEL(m). + RETURNING(table.Signal.AllColumns) + return db.ExecuteOne[model.Signal](ctx, statement) +} diff --git a/db/query/public/site.go b/db/query/public/site.go new file mode 100644 index 00000000..5959b8d0 --- /dev/null +++ b/db/query/public/site.go @@ -0,0 +1,38 @@ +package public + +import ( + "context" + "errors" + "fmt" + //"time" + + //"github.com/Gleipnir-Technology/bob" + "github.com/Gleipnir-Technology/nidus-sync/db" + "github.com/Gleipnir-Technology/nidus-sync/db/gen/nidus-sync/public/model" + "github.com/Gleipnir-Technology/nidus-sync/db/gen/nidus-sync/public/table" + "github.com/go-jet/jet/v2/postgres" +) + +func SiteFromAddressIDForOrg(ctx context.Context, txn db.Ex, address_id int64, org_id int64) (*model.Site, error) { + statement := table.Site.SELECT( + table.Site.AllColumns, + ).FROM(table.Site). + WHERE(table.Site.AddressID.EQ(postgres.Int(address_id)).AND( + table.Site.OrganizationID.EQ(postgres.Int(org_id)))) + result, err := db.ExecuteOneTx[model.Site](ctx, txn, statement) + if err != nil { + if errors.Is(err, db.ErrNoRows) { + return nil, nil + } + return nil, fmt.Errorf("query: %w", err) + } + return &result, nil +} +func SiteFromIDForOrg(ctx context.Context, comm_id int64, org_id int64) (model.Site, error) { + statement := table.Site.SELECT( + table.Site.AllColumns, + ).FROM(table.Site). + WHERE(table.Site.ID.EQ(postgres.Int(comm_id)).AND( + table.Site.OrganizationID.EQ(postgres.Int(org_id)))) + return db.ExecuteOne[model.Site](ctx, statement) +} diff --git a/db/query/publicreport/compliance.go b/db/query/publicreport/compliance.go new file mode 100644 index 00000000..92f958f6 --- /dev/null +++ b/db/query/publicreport/compliance.go @@ -0,0 +1,34 @@ +package publicreport + +import ( + "context" + //"time" + + //"github.com/Gleipnir-Technology/bob" + "github.com/Gleipnir-Technology/nidus-sync/db" + "github.com/Gleipnir-Technology/nidus-sync/db/gen/nidus-sync/publicreport/model" + "github.com/Gleipnir-Technology/nidus-sync/db/gen/nidus-sync/publicreport/table" + "github.com/go-jet/jet/v2/postgres" +) + +type ComplianceUpdater = db.Updater[table.ComplianceTable, model.Compliance] + +func NewUpdaterCompliance() db.Updater[table.ComplianceTable, model.Compliance] { + return db.NewUpdater[table.ComplianceTable, model.Compliance]( + *table.Compliance, + table.Compliance.ReportID, + ) + +} +func ComplianceFromID(ctx context.Context, txn db.Tx, report_id int64) (model.Compliance, error) { + statement := table.Report.SELECT( + table.Compliance.AllColumns, + ).FROM(table.Compliance). + WHERE(table.Compliance.ReportID.EQ(postgres.Int(report_id))) + return db.ExecuteOneTx[model.Compliance](ctx, txn, statement) +} +func ComplianceInsert(ctx context.Context, txn db.Ex, m model.Compliance) (model.Compliance, error) { + statement := table.Compliance.INSERT(table.Compliance.AllColumns). + MODEL(m) + return db.ExecuteOneTx[model.Compliance](ctx, txn, statement) +} diff --git a/db/query/publicreport/image.go b/db/query/publicreport/image.go new file mode 100644 index 00000000..b879ecb4 --- /dev/null +++ b/db/query/publicreport/image.go @@ -0,0 +1,16 @@ +package publicreport + +import ( + "context" + + "github.com/Gleipnir-Technology/nidus-sync/db" + "github.com/Gleipnir-Technology/nidus-sync/db/gen/nidus-sync/publicreport/model" + "github.com/Gleipnir-Technology/nidus-sync/db/gen/nidus-sync/publicreport/table" + //"github.com/go-jet/jet/v2/postgres" +) + +func ImageInsert(ctx context.Context, txn db.Ex, m model.Image) (model.Image, error) { + statement := table.Image.INSERT(table.Image.AllColumns). + MODEL(m) + return db.ExecuteOneTx[model.Image](ctx, txn, statement) +} diff --git a/db/query/publicreport/image_exif.go b/db/query/publicreport/image_exif.go new file mode 100644 index 00000000..f7dbd312 --- /dev/null +++ b/db/query/publicreport/image_exif.go @@ -0,0 +1,20 @@ +package publicreport + +import ( + "context" + + //"github.com/Gleipnir-Technology/bob" + "github.com/Gleipnir-Technology/nidus-sync/db" + //"github.com/Gleipnir-Technology/nidus-sync/db/gen/nidus-sync/public/enum" + "github.com/Gleipnir-Technology/nidus-sync/db/gen/nidus-sync/publicreport/model" + "github.com/Gleipnir-Technology/nidus-sync/db/gen/nidus-sync/publicreport/table" + //"github.com/go-jet/jet/v2/postgres" +) + +func ImageExifInserts(ctx context.Context, txn db.Ex, image_exifs []model.ImageExif) ([]model.ImageExif, error) { + statement := table.ImageExif. + INSERT(table.ImageExif.MutableColumns). + MODELS(image_exifs). + RETURNING(table.ImageExif.AllColumns) + return db.ExecuteManyTx[model.ImageExif](ctx, txn, statement) +} diff --git a/db/query/publicreport/nuisance.go b/db/query/publicreport/nuisance.go new file mode 100644 index 00000000..eefe7f5b --- /dev/null +++ b/db/query/publicreport/nuisance.go @@ -0,0 +1,17 @@ +package publicreport + +import ( + "context" + //"time" + + "github.com/Gleipnir-Technology/nidus-sync/db" + "github.com/Gleipnir-Technology/nidus-sync/db/gen/nidus-sync/publicreport/model" + "github.com/Gleipnir-Technology/nidus-sync/db/gen/nidus-sync/publicreport/table" + //"github.com/go-jet/jet/v2/postgres" +) + +func NuisanceInsert(ctx context.Context, txn db.Ex, m model.Nuisance) (model.Nuisance, error) { + statement := table.Nuisance.INSERT(table.Nuisance.AllColumns). + MODEL(m) + return db.ExecuteOneTx[model.Nuisance](ctx, txn, statement) +} diff --git a/db/query/publicreport/report.go b/db/query/publicreport/report.go index 27db9f8f..5e8ed429 100644 --- a/db/query/publicreport/report.go +++ b/db/query/publicreport/report.go @@ -1,7 +1,9 @@ -package public +package publicreport import ( "context" + "errors" + "fmt" //"time" //"github.com/Gleipnir-Technology/bob" @@ -11,15 +13,21 @@ import ( "github.com/go-jet/jet/v2/postgres" ) -/* - func CommunicationInsert(ctx context.Context, txn bob.Tx, m *model.Communication) (*model.Communication, error) { - m.Created = time.Now() - statement := table.Communication.INSERT(table.Communication.MutableColumns). - MODEL(m) - return db.ExecuteOne[model.Communication](ctx, statement) - } -*/ -func PublicReportsFromIDs(ctx context.Context, report_ids []int64) ([]*model.Report, error) { +type ReportUpdater = db.Updater[table.ReportTable, model.Report] + +func ReportInsert(ctx context.Context, txn db.Ex, m model.Report) (model.Report, error) { + statement := table.Report.INSERT(table.Report.AllColumns). + MODEL(m) + return db.ExecuteOneTx[model.Report](ctx, txn, statement) +} +func ReportFromID(ctx context.Context, report_id int64) (model.Report, error) { + statement := table.Report.SELECT( + table.Report.AllColumns, + ).FROM(table.Report). + WHERE(table.Report.ID.EQ(postgres.Int(report_id))) + return db.ExecuteOne[model.Report](ctx, statement) +} +func ReportsFromIDs(ctx context.Context, report_ids []int64) ([]model.Report, error) { sql_ids := make([]postgres.Expression, len(report_ids)) for i, report_id := range report_ids { sql_ids[i] = postgres.Int(report_id) @@ -30,3 +38,32 @@ func PublicReportsFromIDs(ctx context.Context, report_ids []int64) ([]*model.Rep WHERE(table.Report.ID.IN(sql_ids...)) return db.ExecuteMany[model.Report](ctx, statement) } +func ReportFromPublicID(ctx context.Context, txn db.Ex, public_id string) (*model.Report, error) { + statement := table.Report.SELECT( + table.Report.AllColumns, + ).FROM(table.Report). + WHERE(table.Report.PublicID.EQ(postgres.String(public_id))) + result, err := db.ExecuteOneTx[model.Report](ctx, txn, statement) + if err != nil { + if errors.Is(err, db.ErrNoRows) { + return nil, nil + } + return nil, fmt.Errorf("query: %w", err) + } + return &result, nil +} +func ReportFromPublicIDForOrg(ctx context.Context, txn db.Ex, public_id string, org_id int64) (*model.Report, error) { + statement := table.Report.SELECT( + table.Report.AllColumns, + ).FROM(table.Report). + WHERE(table.Report.PublicID.EQ(postgres.String(public_id)).AND( + table.Report.OrganizationID.EQ(postgres.Int(org_id)))) + result, err := db.ExecuteOneTx[model.Report](ctx, txn, statement) + if err != nil { + if errors.Is(err, db.ErrNoRows) { + return nil, nil + } + return nil, fmt.Errorf("query: %w", err) + } + return &result, nil +} diff --git a/db/query/publicreport/report_image.go b/db/query/publicreport/report_image.go new file mode 100644 index 00000000..1560e9c0 --- /dev/null +++ b/db/query/publicreport/report_image.go @@ -0,0 +1,21 @@ +package publicreport + +import ( + "context" + + "github.com/Gleipnir-Technology/nidus-sync/db" + "github.com/Gleipnir-Technology/nidus-sync/db/gen/nidus-sync/publicreport/model" + "github.com/Gleipnir-Technology/nidus-sync/db/gen/nidus-sync/publicreport/table" + //"github.com/go-jet/jet/v2/postgres" +) + +func ReportImageInsert(ctx context.Context, txn db.Ex, m model.ReportImage) (model.ReportImage, error) { + statement := table.ReportImage.INSERT(table.ReportImage.AllColumns). + MODEL(m) + return db.ExecuteOneTx[model.ReportImage](ctx, txn, statement) +} +func ReportImagesInsert(ctx context.Context, txn db.Ex, m []model.ReportImage) ([]model.ReportImage, error) { + statement := table.ReportImage.INSERT(table.ReportImage.AllColumns). + MODELS(m) + return db.ExecuteManyTx[model.ReportImage](ctx, txn, statement) +} diff --git a/db/query/publicreport/report_log.go b/db/query/publicreport/report_log.go new file mode 100644 index 00000000..a7e099f2 --- /dev/null +++ b/db/query/publicreport/report_log.go @@ -0,0 +1,16 @@ +package publicreport + +import ( + "context" + + "github.com/Gleipnir-Technology/nidus-sync/db" + "github.com/Gleipnir-Technology/nidus-sync/db/gen/nidus-sync/publicreport/model" + "github.com/Gleipnir-Technology/nidus-sync/db/gen/nidus-sync/publicreport/table" + //"github.com/go-jet/jet/v2/postgres" +) + +func ReportLogInsert(ctx context.Context, txn db.Ex, m model.ReportLog) (model.ReportLog, error) { + statement := table.ReportLog.INSERT(table.ReportLog.AllColumns). + MODEL(m) + return db.ExecuteOneTx[model.ReportLog](ctx, txn, statement) +} diff --git a/db/query/publicreport/water.go b/db/query/publicreport/water.go new file mode 100644 index 00000000..eb4d9c77 --- /dev/null +++ b/db/query/publicreport/water.go @@ -0,0 +1,17 @@ +package publicreport + +import ( + "context" + //"time" + + "github.com/Gleipnir-Technology/nidus-sync/db" + "github.com/Gleipnir-Technology/nidus-sync/db/gen/nidus-sync/publicreport/model" + "github.com/Gleipnir-Technology/nidus-sync/db/gen/nidus-sync/publicreport/table" + //"github.com/go-jet/jet/v2/postgres" +) + +func WaterInsert(ctx context.Context, txn db.Ex, m model.Water) (model.Water, error) { + statement := table.Water.INSERT(table.Water.AllColumns). + MODEL(m) + return db.ExecuteOneTx[model.Water](ctx, txn, statement) +} diff --git a/db/tx.go b/db/tx.go new file mode 100644 index 00000000..c3ce2257 --- /dev/null +++ b/db/tx.go @@ -0,0 +1,83 @@ +package db + +import ( + "context" + "database/sql" + "fmt" + + "github.com/jackc/pgx/v5" + "github.com/jackc/pgx/v5/pgconn" + "github.com/rs/zerolog/log" + //"github.com/stephenafamo/scan" +) + +type Ex interface { + Exec(ctx context.Context, sql string, arguments ...any) (commandTag pgconn.CommandTag, err error) + Query(ctx context.Context, sql string, args ...any) (pgx.Rows, error) +} +type Tx struct { + pgx.Tx +} + +func (txn Tx) ExecContext(ctx context.Context, query string, args ...any) (sql.Result, error) { + result, err := txn.Tx.Exec(ctx, query, args...) + if err != nil { + return Result{}, fmt.Errorf("exec: %w", err) + } + return Result{ + tag: result, + }, nil +} + +/* + func (txn Tx) QueryContext(ctx context.Context, query string, args ...any) (scan.Rows, error) { + result, err := txn.Tx.Exec(ctx, query, args...) + return Rows{ + tag: result, + }, err + } +*/ +type Result struct { + tag pgconn.CommandTag +} + +func (r Result) LastInsertId() (int64, error) { + log.Debug().Msg("queried last insert id. erroring...") + return 0, fmt.Errorf("not implemented") +} +func (r Result) RowsAffected() (int64, error) { + rows := r.tag.RowsAffected() + log.Debug().Int64("rows", rows).Msg("queried rows affected") + return rows, nil +} + +type Rows struct { + tag pgconn.CommandTag +} + +func (r Rows) Close() error { + log.Debug().Msg("requested close of rows") + return nil +} +func (r Rows) Columns() ([]string, error) { + log.Debug().Msg("requested columns") + return []string{}, nil +} +func (r Rows) Err() error { + log.Debug().Msg("requested err") + return nil +} +func (r Rows) Next() bool { + log.Debug().Msg("requested next") + return false +} +func (r Rows) Scan(args ...any) error { + log.Debug().Msg("requested scan") + return fmt.Errorf("scan not implemented") +} +func BeginTxn(ctx context.Context) (Tx, error) { + txn, err := PGInstance.PGXPool.BeginTx(ctx, pgx.TxOptions{}) + return Tx{ + Tx: txn, + }, err +} diff --git a/db/types/box2d.go b/db/types/box2d.go deleted file mode 100644 index 785fad62..00000000 --- a/db/types/box2d.go +++ /dev/null @@ -1,8 +0,0 @@ -package types - -type Box2D struct { - XMax float64 - YMax float64 - XMin float64 - YMin float64 -} diff --git a/db/updater.go b/db/updater.go new file mode 100644 index 00000000..1d6fdf9f --- /dev/null +++ b/db/updater.go @@ -0,0 +1,64 @@ +package db + +import ( + "context" + + //"github.com/go-jet/jet/v2" + "github.com/go-jet/jet/v2/postgres" +) + +type Updater[T postgres.Table, M any] struct { + Columns postgres.ColumnList + //Columns []jet.Column + Model M + Table T + + buildWhere func(pk_values ...interface{}) postgres.BoolExpression +} + +func (u Updater[T, M]) Execute(ctx context.Context, txn Ex, pk_values ...interface{}) error { + statement := u.Table. + UPDATE(u.Columns). + MODEL(u.Model). + WHERE(u.buildWhere(pk_values...)) + return ExecuteNoneTx(ctx, txn, statement) +} +func (u Updater[T, M]) Has(c postgres.Column) bool { + for _, col := range u.Columns { + if col == c { + return true + } + } + return false +} +func (u *Updater[T, M]) Set(c postgres.Column) { + u.Columns = append(u.Columns, c) +} +func (u *Updater[T, M]) Unset(c postgres.Column) { + var index = -1 + for i, col := range u.Columns { + if col == c { + index = i + } + } + if index > -1 { + u.Columns[index] = u.Columns[len(u.Columns)-1] + u.Columns = u.Columns[:len(u.Columns)-1] + } +} +func NewUpdater[T postgres.Table, M any]( + table T, + pk_columns ...postgres.ColumnInteger, +) Updater[T, M] { + return Updater[T, M]{ + Columns: postgres.ColumnList{}, + Table: table, + buildWhere: func(pk_values ...interface{}) postgres.BoolExpression { + conditions := make([]postgres.BoolExpression, len(pk_columns)) + for i, col := range pk_columns { + conditions[i] = col.EQ(postgres.Int64(pk_values[i].(int64))) + } + return postgres.AND(conditions...) + }, + } +} diff --git a/geomutil/geomutil.go b/geomutil/geomutil.go new file mode 100644 index 00000000..1d8767c0 --- /dev/null +++ b/geomutil/geomutil.go @@ -0,0 +1,9 @@ +package geomutil + +import ( + "github.com/twpayne/go-geom" +) + +func PointFromLngLat(lng, lat float64) geom.T { + return geom.NewPointFlat(geom.XY, []float64{lng, lat}) +} diff --git a/go.mod b/go.mod index cc1a6476..e54590ce 100644 --- a/go.mod +++ b/go.mod @@ -16,7 +16,6 @@ require ( github.com/disintegration/imaging v1.6.2 github.com/getsentry/sentry-go v0.42.0 github.com/getsentry/sentry-go/zerolog v0.42.0 - github.com/go-jet/jet v2.3.0+incompatible github.com/go-jet/jet/v2 v2.14.1 github.com/google/go-querystring v1.2.0 github.com/google/uuid v1.6.0 @@ -24,7 +23,7 @@ require ( github.com/gorilla/schema v1.4.1 github.com/gorilla/websocket v1.5.3 github.com/jackc/pgx/v5 v5.7.6 - github.com/lib/pq v1.10.9 + github.com/lib/pq v1.12.3 github.com/maruel/genai v0.0.0-20251221000642-77279d1194c1 github.com/minio/minio-go/v7 v7.0.97 github.com/nyaruka/phonenumbers v1.6.8 @@ -59,11 +58,8 @@ require ( github.com/golang-jwt/jwt/v5 v5.2.2 // indirect github.com/golang/mock v1.6.0 // indirect github.com/invopop/jsonschema v0.13.0 // indirect - github.com/jackc/chunkreader/v2 v2.0.1 // indirect - github.com/jackc/pgconn v1.14.3 // indirect github.com/jackc/pgio v1.0.0 // indirect github.com/jackc/pgpassfile v1.0.0 // indirect - github.com/jackc/pgproto3/v2 v2.3.3 // indirect github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect github.com/jackc/pgtype v1.14.4 // indirect github.com/jackc/puddle/v2 v2.2.2 // indirect @@ -93,7 +89,9 @@ require ( github.com/tidwall/rtree v1.3.1 // indirect github.com/tidwall/sjson v1.2.4 // indirect github.com/tinylib/msgp v1.3.0 // indirect + github.com/twpayne/go-geom v1.6.1 // indirect github.com/twpayne/go-proj/v11 v11.0.0 // indirect + github.com/twpayne/pgx-geom v1.0.0 // indirect github.com/wk8/go-ordered-map/v2 v2.1.8 // indirect go.mongodb.org/mongo-driver v1.11.4 // indirect go.uber.org/multierr v1.11.0 // indirect @@ -108,3 +106,4 @@ require ( // replace github.com/stephenafamo/bob v0.42.0 => ../bob // replace github.com/Gleipnir-Technology/arcgis-go v0.0.12 => ./arcgis-go +replace github.com/go-jet/jet/v2 v2.14.1 => ../jet diff --git a/go.sum b/go.sum index 87772a3e..b4dd0545 100644 --- a/go.sum +++ b/go.sum @@ -85,10 +85,6 @@ github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxI github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= github.com/go-ini/ini v1.67.0 h1:z6ZrTEZqSWOTyH2FlglNbNgARyHG8oLW9gMELqKr06A= github.com/go-ini/ini v1.67.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8= -github.com/go-jet/jet v2.3.0+incompatible h1:Yg7JSERDC0f9x3dHUBMA2cxe9/qC6qlozDDO/s38USU= -github.com/go-jet/jet v2.3.0+incompatible/go.mod h1:XgTt00fj8pAXMKe1ETL9R/kZWWyi2j/ymuH+gaW+EdI= -github.com/go-jet/jet/v2 v2.14.1 h1:wsfD9e7CGP9h46+IFNlftfncBcmVnKddikbTtapQM3M= -github.com/go-jet/jet/v2 v2.14.1/go.mod h1:dqTAECV2Mo3S2NFjbm4vJ1aDruZjhaJ1RAAR8rGUkkc= github.com/go-json-experiment/json v0.0.0-20250725192818-e39067aee2d2 h1:iizUGZ9pEquQS5jTGkh4AqeeHCMbfbjeb0zMt0aEFzs= github.com/go-json-experiment/json v0.0.0-20250725192818-e39067aee2d2/go.mod h1:TiCD2a1pcmjd7YnhGH0f/zKNcCD06B029pHhzV23c2M= github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= @@ -136,6 +132,7 @@ github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUq github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg= github.com/invopop/jsonschema v0.13.0 h1:KvpoAJWEjR3uD9Kbm2HWJmqsEaHt8lBUpd0qHcIi21E= github.com/invopop/jsonschema v0.13.0/go.mod h1:ffZ5Km5SWWRAIN6wbDXItl95euhFz2uON45H2qjYt+0= +github.com/jackc/chunkreader v1.0.0 h1:4s39bBR8ByfqH+DKm8rQA3E1LHZWB9XWcrz8fqaZbe0= github.com/jackc/chunkreader v1.0.0/go.mod h1:RT6O25fNZIuasFJRyZ4R/Y2BbhasbmZXF9QQ7T3kePo= github.com/jackc/chunkreader/v2 v2.0.0/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk= github.com/jackc/chunkreader/v2 v2.0.1 h1:i+RDz65UE+mmpjTfyz0MoVTnzeYxroil2G82ki7MGG8= @@ -152,10 +149,10 @@ github.com/jackc/pgio v1.0.0 h1:g12B9UwVnzGhueNavwioyEEpAmqMe1E/BN9ES+8ovkE= github.com/jackc/pgio v1.0.0/go.mod h1:oP+2QK2wFfUWgr+gxjoBH9KGBb31Eio69xUb0w5bYf8= github.com/jackc/pgmock v0.0.0-20190831213851-13a1b77aafa2/go.mod h1:fGZlG77KXmcq05nJLRkk0+p82V8B8Dw8KN2/V9c/OAE= github.com/jackc/pgmock v0.0.0-20201204152224-4fe30f7445fd/go.mod h1:hrBW0Enj2AZTNpt/7Y5rr2xe/9Mn757Wtb2xeBzPv2c= -github.com/jackc/pgmock v0.0.0-20210724152146-4ad1a8207f65 h1:DadwsjnMwFjfWc9y5Wi/+Zz7xoE5ALHsRQlOctkOiHc= github.com/jackc/pgmock v0.0.0-20210724152146-4ad1a8207f65/go.mod h1:5R2h2EEX+qri8jOWMbJCtaPWkrrNc7OHwsp2TCqp7ak= github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= +github.com/jackc/pgproto3 v1.1.0 h1:FYYE4yRw+AgI8wXIinMlNjBbp/UitDJwfj5LqqewP1A= github.com/jackc/pgproto3 v1.1.0/go.mod h1:eR5FA3leWg7p9aeAqi37XOTgTIbkABlvcPB3E5rlc78= github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190420180111-c116219b62db/go.mod h1:bhq50y+xrl9n5mRYyCBFKkpRVTLYJVWeCc+mEAI3yXA= github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190609003834-432c2951c711/go.mod h1:uH0AWtUmuShn0bcesswc4aBTWGvw0cAxIJp+6OB//Wg= @@ -180,9 +177,8 @@ github.com/jackc/pgx/v4 v4.0.0-20190420224344-cc3461e65d96/go.mod h1:mdxmSJJuR08 github.com/jackc/pgx/v4 v4.0.0-20190421002000-1b8f0016e912/go.mod h1:no/Y67Jkk/9WuGR0JG/JseM9irFbnEPbuWV2EELPNuM= github.com/jackc/pgx/v4 v4.0.0-pre1.0.20190824185557-6972a5742186/go.mod h1:X+GQnOEnf1dqHGpw7JmHqHc1NxDoalibchSk9/RWuDc= github.com/jackc/pgx/v4 v4.12.1-0.20210724153913-640aa07df17c/go.mod h1:1QD0+tgSXP7iUjYm9C1NxKhny7lq6ee99u/z+IHFcgs= +github.com/jackc/pgx/v4 v4.18.2 h1:xVpYkNR5pk5bMCZGfClbO962UIqVABcAGt7ha1s/FeU= github.com/jackc/pgx/v4 v4.18.2/go.mod h1:Ey4Oru5tH5sB6tV7hDmfWFahwF15Eb7DNXlRKx2CkVw= -github.com/jackc/pgx/v4 v4.18.3 h1:dE2/TrEsGX3RBprb3qryqSV9Y60iZN1C6i8IrmW9/BA= -github.com/jackc/pgx/v4 v4.18.3/go.mod h1:Ey4Oru5tH5sB6tV7hDmfWFahwF15Eb7DNXlRKx2CkVw= github.com/jackc/pgx/v5 v5.5.4/go.mod h1:ez9gk+OAat140fv9ErkZDYFWmXLfV+++K0uAOiwgm1A= github.com/jackc/pgx/v5 v5.7.6 h1:rWQc5FwZSPX58r1OQmkuaNicxdmExaEz5A2DO2hUuTk= github.com/jackc/pgx/v5 v5.7.6/go.mod h1:aruU7o91Tc2q2cFp5h4uP3f6ztExVpyVv88Xl/8Vl8M= @@ -220,8 +216,8 @@ github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.10.2/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= -github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= -github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/lib/pq v1.12.3 h1:tTWxr2YLKwIvK90ZXEw8GP7UFHtcbTtty8zsI+YjrfQ= +github.com/lib/pq v1.12.3/go.mod h1:/p+8NSbOcwzAEI7wiMXFlgydTwcgTr3OSKMsD2BitpA= github.com/localtunnel/go-localtunnel v0.0.0-20170326223115-8a804488f275 h1:IZycmTpoUtQK3PD60UYBwjaCUHUP7cML494ao9/O8+Q= github.com/localtunnel/go-localtunnel v0.0.0-20170326223115-8a804488f275/go.mod h1:zt6UU74K6Z6oMOYJbJzYpYucqdcQwSMPBEdSvGiaUMw= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4= @@ -390,8 +386,12 @@ github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+F github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY= github.com/twilio/twilio-go v1.29.1 h1:4dx1d9EhRUhL5ubzYrDROERAiw55s7mBE6/w3q2epVg= github.com/twilio/twilio-go v1.29.1/go.mod h1:FpgNWMoD8CFnmukpKq9RNpUSGXC0BwnbeKZj2YHlIkw= +github.com/twpayne/go-geom v1.6.1 h1:iLE+Opv0Ihm/ABIcvQFGIiFBXd76oBIar9drAwHFhR4= +github.com/twpayne/go-geom v1.6.1/go.mod h1:Kr+Nly6BswFsKM5sd31YaoWS5PeDDH2NftJTK7Gd028= github.com/twpayne/go-proj/v11 v11.0.0 h1:jkGRE2DOwxhbn2hPnps1wNepdCgA8JB/K8rJosVR2jM= github.com/twpayne/go-proj/v11 v11.0.0/go.mod h1:2qEvCqcSQqaKRxHc8K6F5THAzS/SVknfWVPnTHFqE3M= +github.com/twpayne/pgx-geom v1.0.0 h1:6G4KAY8eJctjXhvGck73S7HnKayly7ZyQcmG8TC1CDU= +github.com/twpayne/pgx-geom v1.0.0/go.mod h1:d+aJjVsx0FSBzl9DnFfJyMd0IZs6GzGwpSir5vLtWXU= github.com/uber/h3-go/v4 v4.4.0 h1:sCHcZHvIKEbdt4rY5ZVs2HDNlCy2wXeJ98vAbz+iLok= github.com/uber/h3-go/v4 v4.4.0/go.mod h1:c94kwXZNHVWkZGIN+y9dV81YVEttypqJpOjsmXGr68Y= github.com/wasilibs/go-pgquery v0.0.0-20250409022910-10ac41983c07 h1:mJdDDPblDfPe7z7go8Dvv1AJQDI3eQ/5xith3q2mFlo= diff --git a/platform/address.go b/platform/address.go index e151c3e1..07d0590a 100644 --- a/platform/address.go +++ b/platform/address.go @@ -46,10 +46,7 @@ func AddressFromComplianceReportRequestID(ctx context.Context, public_id string) return row, nil } -func AddressLocation(ctx context.Context, address *models.Address) (*types.Location, error) { - if address == nil { - return nil, fmt.Errorf("nil address") - } +func AddressLocation(ctx context.Context, address types.Address) (*types.Location, error) { row, err := bob.One(ctx, db.PGInstance.BobDB, psql.Select( sm.Columns( models.Addresses.Columns.LocationLatitude.As("latitude"), @@ -63,3 +60,7 @@ func AddressLocation(ctx context.Context, address *models.Address) (*types.Locat } return row, nil } + +func AddressInsert(ctx context.Context) (*types.Address, error) { + return nil, nil +} diff --git a/platform/address/address.go b/platform/address/address.go new file mode 100644 index 00000000..d7f783d3 --- /dev/null +++ b/platform/address/address.go @@ -0,0 +1,100 @@ +package address + +import ( + "context" + "fmt" + "time" + + "github.com/Gleipnir-Technology/nidus-sync/db" + "github.com/Gleipnir-Technology/nidus-sync/db/gen/nidus-sync/public/model" + querypublic "github.com/Gleipnir-Technology/nidus-sync/db/query/public" + "github.com/Gleipnir-Technology/nidus-sync/h3utils" + "github.com/Gleipnir-Technology/nidus-sync/platform/types" + "github.com/Gleipnir-Technology/nidus-sync/stadia" + "github.com/rs/zerolog/log" + "github.com/twpayne/go-geom" +) + +func InsertAddress(ctx context.Context, txn db.Ex, address types.Address) (types.Address, error) { + lng := address.Location.Longitude + lat := address.Location.Latitude + cell, err := h3utils.GetCell(lng, lat, 15) + if err != nil { + return types.Address{}, fmt.Errorf("failed to convert lat %f lng %f to h3 cell", lat, lng) + } + addr := model.Address{ + Country: address.Country, + Created: time.Now(), + Gid: address.GID, + H3cell: cell.String(), + //ID: + Locality: address.Locality, + Location: address.Location.ToGeom(), + Number: address.Number, + PostalCode: address.PostalCode, + Region: address.Region, + Street: address.Street, + Unit: "", + } + m, err := querypublic.AddressInsert(ctx, txn, addr) + if err != nil { + return types.Address{}, fmt.Errorf("address insert: %w", err) + } + log.Info().Int32("id", m.ID).Msg("inserted address") + return types.AddressFromModel(m), nil +} +func InsertAddressFeature(ctx context.Context, txn db.Ex, feature stadia.GeocodeFeature) (types.Address, error) { + m, err := addressModelFromFeature(feature) + if err != nil { + return types.Address{}, fmt.Errorf("address from feature: %w", err) + } + row, err := querypublic.AddressInsert(ctx, txn, m) + if err != nil { + return types.Address{}, fmt.Errorf("address insert: %w", err) + } + return types.AddressFromModel(row), nil +} +func InsertAddresses(ctx context.Context, txn db.Ex, features []stadia.GeocodeFeature) ([]types.Address, error) { + models := make([]model.Address, len(features)) + for i, feature := range features { + m, err := addressModelFromFeature(feature) + if err != nil { + return nil, fmt.Errorf("address from feature: %w", err) + } + models[i] = m + } + addresses, err := querypublic.AddressInserts(ctx, txn, models) + if err != nil { + return nil, fmt.Errorf("inserts: %w", err) + } + results := make([]types.Address, len(addresses)) + for i, address := range addresses { + results[i] = types.AddressFromModel(address) + } + return results, nil +} +func geomFromLngLat(lng, lat float64) geom.T { + return geom.NewPointFlat(geom.XY, []float64{lng, lat}) +} +func addressModelFromFeature(feature stadia.GeocodeFeature) (model.Address, error) { + lng := feature.Geometry.Coordinates[0] + lat := feature.Geometry.Coordinates[1] + cell, err := h3utils.GetCell(lng, lat, 15) + if err != nil { + return model.Address{}, fmt.Errorf("failed to convert lat %f lng %f to h3 cell", lat, lng) + } + return model.Address{ + Country: feature.CountryCode(), + Created: time.Now(), + Gid: feature.Properties.GID, + H3cell: cell.String(), + //ID: + Locality: feature.Locality(), + Location: geomFromLngLat(lng, lat), + Number: feature.Number(), + PostalCode: feature.PostalCode(), + Region: feature.Region(), + Street: feature.Street(), + Unit: "", + }, nil +} diff --git a/platform/arcgis.go b/platform/arcgis.go index bc3e903d..bbaac73f 100644 --- a/platform/arcgis.go +++ b/platform/arcgis.go @@ -34,7 +34,6 @@ import ( "github.com/Gleipnir-Technology/nidus-sync/db/models" queryarcgis "github.com/Gleipnir-Technology/nidus-sync/db/query/arcgis" "github.com/Gleipnir-Technology/nidus-sync/db/sql" - "github.com/Gleipnir-Technology/nidus-sync/db/types" "github.com/Gleipnir-Technology/nidus-sync/debug" "github.com/Gleipnir-Technology/nidus-sync/h3utils" "github.com/Gleipnir-Technology/nidus-sync/lint" @@ -45,6 +44,7 @@ import ( "github.com/jackc/pgx/v5" "github.com/rs/zerolog" "github.com/rs/zerolog/log" + "github.com/twpayne/go-geom" "github.com/uber/h3-go/v4" ) @@ -57,7 +57,7 @@ func HasFieldseekerConnection(ctx context.Context, user_id int32) (bool, error) if err != nil { return false, err } - return *result, nil + return result, nil } func IsSyncOngoing(org_id int32) bool { @@ -74,7 +74,7 @@ func getOAuthForOrg(ctx context.Context, org *models.Organization) (*model.OAuth return nil, fmt.Errorf("Failed to query all oauth tokens for org: %w", err) } for _, oauth := range oauths { - return oauth, nil + return &oauth, nil } } return nil, nil @@ -100,9 +100,9 @@ func refreshFieldseekerData(background_ctx context.Context, newOauthCh <-chan st wg.Add(1) go func() { defer wg.Done() - err := maintainOAuth(workerCtx, oauth) + err := maintainOAuth(workerCtx, &oauth) if err != nil { - markTokenFailed(ctx, oauth) + markTokenFailed(ctx, &oauth) if errors.Is(err, arcgis.ErrorInvalidRefreshToken) { log.Info().Int("oauth_token.id", int(oauth.ID)).Msg("Marked invalid by the server") } else { @@ -259,7 +259,7 @@ func updateArcgisUserData(ctx context.Context, user *models.User, oauth *model.O ArcgisID: &ag_user.ID, ArcgisLicenseTypeID: &ag_user.UserLicenseTypeID, } - err = queryarcgis.OAuthTokenUpdateLicense(ctx, oauth.RefreshToken, &model) + err = queryarcgis.OAuthTokenUpdateLicense(ctx, oauth.RefreshToken, model) if err != nil { log.Error().Err(err).Msg("Failed to update oauth token portal data") return @@ -402,7 +402,7 @@ func updateArcgisAccount(ctx context.Context, txn bob.Tx, client *arcgis.ArcGIS, } } log.Info().Str("username", p.User.Username).Str("user_id", p.User.ID).Str("org_id", p.User.OrgID).Str("org_name", p.Name).Str("license_type_id", p.User.UserLicenseTypeID).Msg("Updated portals data") - return account, ag_user, nil + return account, &ag_user, nil } func updateServiceData(ctx context.Context, txn bob.Tx, client *arcgis.ArcGIS, user *models.User, account *model.Account) error { service_maps, err := client.MapServices(ctx) @@ -460,19 +460,20 @@ func ensureServiceFeature(ctx context.Context, txn bob.Tx, client *arcgis.ArcGIS return fmt.Errorf("populate metadata: %w", err) } + extent := geom.NewBounds(geom.XY) + extent.SetCoords( + []float64{metadata.FullExtent.Xmin, metadata.FullExtent.Ymin}, + []float64{metadata.FullExtent.Xmax, metadata.FullExtent.Ymax}, + ) + setter := model.ServiceFeature{ - AccountID: &account.ID, - Extent: types.Box2D{ - XMax: 180, - YMax: 90, - XMin: -180, - YMin: -90, - }, + AccountID: &account.ID, + Extent: *extent, ItemID: metadata.ServiceItemId, SpatialReference: int32(*metadata.SpatialReference.LatestWKID), URL: service.URL.String(), } - return queryarcgis.ServiceFeatureInsert(ctx, txn, &setter) + return queryarcgis.ServiceFeatureInsert(ctx, txn, setter) } func maybeCreateWebhook(ctx context.Context, client *fieldseeker.FieldSeeker) { @@ -640,12 +641,12 @@ func maintainOAuth(ctx context.Context, aot *model.OAuthToken) error { case <-ctx.Done(): return nil case <-accessTokenTicker.C: - err := oauth.RefreshAccessToken(ctx, oa) + err := oauth.RefreshAccessToken(ctx, &oa) if err != nil { return fmt.Errorf("Failed to refresh access token: %w", err) } case <-refreshTokenTicker.C: - err := oauth.RefreshRefreshToken(ctx, oa) + err := oauth.RefreshRefreshToken(ctx, &oa) if err != nil { return fmt.Errorf("Failed to maintain refresh token: %w", err) } @@ -1587,7 +1588,7 @@ func ensureArcgisAccount(ctx context.Context, txn bob.Tx, portal *response.Porta return nil, fmt.Errorf("find arcgis account: %w", err) } } - return account, nil + return &account, nil } func updateSummaryTables(ctx context.Context, org *models.Organization) { updateSummaryMosquitoSource(ctx, org) diff --git a/platform/client.go b/platform/client.go index bad32075..6fb14b97 100644 --- a/platform/client.go +++ b/platform/client.go @@ -17,7 +17,7 @@ func EnsureClient(ctx context.Context, client uuid.UUID, user_agent string) erro models.SelectWhere.PublicreportClients.UUID.EQ(client), ).One(ctx, db.PGInstance.BobDB) if err == nil { - log.Debug().Str("client", client.String()).Msg("already exists") + //log.Debug().Str("client", client.String()).Msg("already exists") return nil } else if err != nil && err.Error() != "sql: no rows in result set" { return fmt.Errorf("failed existing client %s: %w", client.String(), err) diff --git a/platform/communication.go b/platform/communication.go index 91d396dc..1e6bb69a 100644 --- a/platform/communication.go +++ b/platform/communication.go @@ -3,14 +3,17 @@ package platform import ( "context" "fmt" + "time" "github.com/Gleipnir-Technology/nidus-sync/db" + //"github.com/Gleipnir-Technology/nidus-sync/db/gen/nidus-sync/public/enum" "github.com/Gleipnir-Technology/nidus-sync/db/gen/nidus-sync/public/model" querypublic "github.com/Gleipnir-Technology/nidus-sync/db/query/public" "github.com/Gleipnir-Technology/nidus-sync/lint" + //"github.com/go-jet/jet/v2/postgres" ) -func CommunicationsForOrganization(ctx context.Context, org_id int64) ([]*model.Communication, error) { +func CommunicationsForOrganization(ctx context.Context, org_id int64) ([]model.Communication, error) { return querypublic.CommunicationsFromOrganization(ctx, org_id) } func CommunicationFromID(ctx context.Context, user User, comm_id int64) (*model.Communication, error) { @@ -21,33 +24,39 @@ func CommunicationFromID(ctx context.Context, user User, comm_id int64) (*model. if comm.OrganizationID != user.Organization.ID { return nil, nil } - return comm, nil + return &comm, nil } -func CommunicationMarkInvalid(ctx context.Context, user User, comm_id int64) error { - return communicationMark(ctx, user, comm_id, querypublic.CommunicationMarkInvalid) +func CommunicationMarkInvalid(ctx context.Context, user User, comm_id int32) error { + return communicationMark(ctx, user, comm_id, model.Communicationstatus_Invalid, model.Communicationlogentry_StatusInvalidated) } -func CommunicationMarkPendingResponse(ctx context.Context, user User, comm_id int64) error { - return communicationMark(ctx, user, comm_id, querypublic.CommunicationMarkPendingResponse) +func CommunicationMarkPendingResponse(ctx context.Context, user User, comm_id int32) error { + return communicationMark(ctx, user, comm_id, model.Communicationstatus_Pending, model.Communicationlogentry_StatusPending) } -func CommunicationMarkPossibleIssue(ctx context.Context, user User, comm_id int64) error { - return communicationMark(ctx, user, comm_id, querypublic.CommunicationMarkPossibleIssue) +func CommunicationMarkPossibleIssue(ctx context.Context, user User, comm_id int32) error { + return communicationMark(ctx, user, comm_id, model.Communicationstatus_PossibleIssue, model.Communicationlogentry_StatusPossibleIssue) } -func CommunicationMarkPossibleResolved(ctx context.Context, user User, comm_id int64) error { - return communicationMark(ctx, user, comm_id, querypublic.CommunicationMarkPossibleResolved) +func CommunicationMarkPossibleResolved(ctx context.Context, user User, comm_id int32) error { + return communicationMark(ctx, user, comm_id, model.Communicationstatus_PossibleResolved, model.Communicationlogentry_StatusPossibleResolved) } -type markFunc = func(context.Context, db.Tx, int64, int64, int64) error - -func communicationMark(ctx context.Context, user User, comm_id int64, f markFunc) error { +func communicationMark(ctx context.Context, user User, comm_id int32, status model.Communicationstatus, log_type model.Communicationlogentry) error { txn, err := db.BeginTxn(ctx) if err != nil { return fmt.Errorf("begin txn: %w", err) } defer lint.LogOnErrRollback(txn.Rollback, ctx, "rollback") - err = f(ctx, txn, int64(user.Organization.ID), int64(user.ID), comm_id) + err = querypublic.CommunicationSetStatus(ctx, txn, int64(user.Organization.ID), int64(comm_id), status) if err != nil { return fmt.Errorf("mark: %w", err) } + user_id := int32(user.ID) + log_entry := model.CommunicationLogEntry{ + CommunicationID: comm_id, + Created: time.Now(), + Type: log_type, + User: &user_id, + } + querypublic.CommunicationLogEntryInsert(ctx, txn, log_entry) txn.Commit(ctx) return nil } diff --git a/platform/district.go b/platform/district.go index a3dbf06c..ecc879f9 100644 --- a/platform/district.go +++ b/platform/district.go @@ -40,7 +40,7 @@ func DistrictForLocation(ctx context.Context, lng float64, lat float64) (*models return nil, errors.New("too many organizations") } } -func matchDistrict(ctx context.Context, location *types.Location, images []ImageUpload, address *models.Address) (int32, error) { +func matchDistrict(ctx context.Context, location *types.Location, images []ImageUpload, address *types.Address) (int32, error) { var err error var org *models.Organization for _, image := range images { @@ -67,7 +67,7 @@ func matchDistrict(ctx context.Context, location *types.Location, images []Image } if address != nil { log.Debug().Msg("doing district match via address...") - location, err = AddressLocation(ctx, address) + location, err = AddressLocation(ctx, *address) if err != nil { return 0, fmt.Errorf("location for address: %w", err) } diff --git a/platform/geocode/address.go b/platform/geocode/address.go index 2d227aaf..6a36d635 100644 --- a/platform/geocode/address.go +++ b/platform/geocode/address.go @@ -3,20 +3,14 @@ package geocode import ( "context" "fmt" - "time" - "github.com/Gleipnir-Technology/bob" - "github.com/Gleipnir-Technology/bob/dialect/psql" - "github.com/Gleipnir-Technology/bob/dialect/psql/dialect" - "github.com/Gleipnir-Technology/bob/dialect/psql/im" - "github.com/Gleipnir-Technology/bob/dialect/psql/sm" - //bobtypes "github.com/Gleipnir-Technology/bob/types" - "github.com/Gleipnir-Technology/nidus-sync/db/models" - "github.com/Gleipnir-Technology/nidus-sync/h3utils" + "github.com/Gleipnir-Technology/nidus-sync/db" + //"github.com/Gleipnir-Technology/nidus-sync/db/gen/nidus-sync/public/model" + querypublic "github.com/Gleipnir-Technology/nidus-sync/db/query/public" + platformaddress "github.com/Gleipnir-Technology/nidus-sync/platform/address" "github.com/Gleipnir-Technology/nidus-sync/platform/types" "github.com/Gleipnir-Technology/nidus-sync/stadia" - "github.com/rs/zerolog/log" - "github.com/stephenafamo/scan" + //"github.com/rs/zerolog/log" ) type _rowWithID struct { @@ -24,157 +18,33 @@ type _rowWithID struct { } // Ensure the provided address exists. If it doesn't add it to the database. -func EnsureAddress(ctx context.Context, txn bob.Executor, a types.Address) (*models.Address, error) { - address, err := models.Addresses.Query( - models.SelectWhere.Addresses.Gid.EQ(a.GID), - ).One(ctx, txn) - if err == nil { - return address, nil - } - id, err := insertAddress(ctx, txn, a) +func EnsureAddress(ctx context.Context, txn db.Ex, a types.Address) (types.Address, error) { + existing, err := querypublic.AddressFromGID(ctx, txn, a.GID) if err != nil { - return nil, fmt.Errorf("insert address: %w", err) + return types.Address{}, fmt.Errorf("query address from gid: %w", err) } - return &models.Address{ - Country: a.Country, - Created: time.Now(), - Gid: a.GID, - H3cell: "", - ID: *id, - Locality: a.Locality, - Location: "", - PostalCode: a.PostalCode, - Street: a.Street, - Unit: a.Unit, - Region: a.Region, - Number: a.Number, - }, nil + if existing != nil { + return types.AddressFromModel(*existing), nil + } + addr, err := platformaddress.InsertAddress(ctx, txn, a) + if err != nil { + return types.Address{}, fmt.Errorf("insert address: %w", err) + } + return addr, nil } -func ensureAddressFromFeature(ctx context.Context, txn bob.Executor, feature stadia.GeocodeFeature) (int32, error) { +func ensureAddressFromFeature(ctx context.Context, txn db.Ex, feature stadia.GeocodeFeature) (types.Address, error) { + var result types.Address if feature.Geometry.Type != "Point" { - return 0, fmt.Errorf("Can't hanlde stadia geometry %s", feature.Geometry.Type) + return result, fmt.Errorf("Can't hanlde stadia geometry %s", feature.Geometry.Type) } - lat := feature.Geometry.Coordinates[1] - lng := feature.Geometry.Coordinates[0] - cell, err := h3utils.GetCell(lng, lat, 15) + existing, err := querypublic.AddressFromGID(ctx, txn, feature.Properties.GID) if err != nil { - return 0, fmt.Errorf("failed to convert lat %f lng %f to h3 cell", lat, lng) + return types.Address{}, fmt.Errorf("query address from gid: %w", err) } - a, err := models.Addresses.Query( - models.SelectWhere.Addresses.Gid.EQ(feature.Properties.GID), - ).One(ctx, txn) - if err != nil && err.Error() != "sql: no rows in result set" { - return 0, fmt.Errorf("query address: %w", err) + if existing != nil { + return types.AddressFromModel(*existing), nil } - if err == nil { - return a.ID, nil - } - query := addressQuery() - query.Apply( - im.Values( - psql.Arg(feature.CountryCode()), - psql.Arg(time.Now()), - psql.Arg(feature.Properties.GID), - psql.Arg(cell.String()), - psql.Raw("DEFAULT"), - psql.Arg(feature.Locality()), - psql.F("ST_Point", lng, lat, 4326), - psql.Arg(feature.Number()), - psql.Arg(feature.PostalCode()), - psql.Arg(feature.Region()), - psql.Arg(feature.Street()), - psql.Raw("''"), - ), - im.OnConflict("gid").DoNothing(), - ) - row, err := bob.One(ctx, txn, query, scan.StructMapper[_rowWithID]()) - log.Info().Int32("id", row.ID).Msg("inserted address") - if err != nil { - return 0, fmt.Errorf("insert: %w", err) - } - return row.ID, nil -} -func insertAddress(ctx context.Context, txn bob.Executor, address types.Address) (*int32, error) { - lng := address.Location.Longitude - lat := address.Location.Latitude - cell, err := h3utils.GetCell(lng, lat, 15) - if err != nil { - return nil, fmt.Errorf("failed to convert lat %f lng %f to h3 cell", lat, lng) - } - query := addressQuery() - query.Apply( - im.Values( - psql.Arg(address.Country), - psql.Arg(time.Now()), - psql.Arg(address.GID), - psql.Arg(cell), - psql.Raw("DEFAULT"), - psql.Arg(address.Locality), - psql.F("ST_Point", address.Location.Longitude, address.Location.Latitude, 4326), - psql.Arg(address.Number), - psql.Arg(address.PostalCode), - psql.Arg(address.Region), - psql.Arg(address.Street), - psql.Raw("''"), - ), - ) - row, err := bob.One(ctx, txn, query, scan.StructMapper[_rowWithID]()) - if err != nil { - return nil, fmt.Errorf("insert: %w", err) - } - return &row.ID, nil -} -func insertAddresses(ctx context.Context, txn bob.Executor, features []stadia.GeocodeFeature) ([]types.Address, error) { - query := addressQuery() - gids := make([]string, len(features)) - for i, feature := range features { - gids[i] = feature.Properties.GID - lng := feature.Geometry.Coordinates[0] - lat := feature.Geometry.Coordinates[1] - cell, err := h3utils.GetCell(lng, lat, 15) - if err != nil { - return nil, fmt.Errorf("failed to convert lat %f lng %f to h3 cell", lat, lng) - } - query.Apply( - im.Values( - psql.Arg(feature.CountryCode()), - psql.Arg(time.Now()), - psql.Arg(feature.Properties.GID), - psql.Arg(cell.String()), - psql.Raw("DEFAULT"), - psql.Arg(feature.Locality()), - psql.F("ST_Point", lng, lat, 4326), - psql.Arg(feature.Number()), - psql.Arg(feature.PostalCode()), - psql.Arg(feature.Region()), - psql.Arg(feature.Street()), - psql.Raw("''"), - ), - im.OnConflict("gid").DoNothing(), - ) - } - _, err := bob.All(ctx, txn, query, scan.StructMapper[_rowWithID]()) - if err != nil { - return nil, fmt.Errorf("insert: %w", err) - } - addresses, err := models.Addresses.Query( - sm.Where( - models.Addresses.Columns.Gid.EQ(psql.Any(gids)), - ), - ).All(ctx, txn) - if err != nil { - return nil, fmt.Errorf("query by gid: %w", err) - } - results := make([]types.Address, len(addresses)) - for i, address := range addresses { - results[i] = types.AddressFromModel(address) - } - return results, nil -} -func addressQuery() bob.BaseQuery[*dialect.InsertQuery] { - return psql.Insert( - im.Into("address", "country", "created", "gid", "h3cell", "id", "locality", "location", "number_", "postal_code", "region", "street", "unit"), - im.Returning("id"), - ) + + return platformaddress.InsertAddressFeature(ctx, txn, feature) } diff --git a/platform/geocode/by_gid.go b/platform/geocode/by_gid.go index 071a7e31..89194a6b 100644 --- a/platform/geocode/by_gid.go +++ b/platform/geocode/by_gid.go @@ -30,7 +30,7 @@ func ByGID(ctx context.Context, gid string) (*GeocodeResult, error) { if err != nil { return nil, fmt.Errorf("latlngtocell: %w", err) } - id, err := ensureAddressFromFeature(ctx, db.PGInstance.BobDB, feature) + addr, err := ensureAddressFromFeature(ctx, db.PGInstance.PGXPool, feature) if err != nil { return nil, fmt.Errorf("insert address: %w", err) } @@ -38,7 +38,7 @@ func ByGID(ctx context.Context, gid string) (*GeocodeResult, error) { Address: types.Address{ Country: feature.Properties.Context.ISO3166A3, GID: feature.Properties.GID, - ID: &id, + ID: addr.ID, Locality: feature.Properties.Context.WhosOnFirst.Locality.Name, Location: &location, Number: feature.Properties.AddressComponents.Number, diff --git a/platform/geocode/geocode.go b/platform/geocode/geocode.go index 6c43e535..af695f02 100644 --- a/platform/geocode/geocode.go +++ b/platform/geocode/geocode.go @@ -17,6 +17,7 @@ import ( "github.com/Gleipnir-Technology/nidus-sync/db/gen/nidus-sync/stadia/table" "github.com/Gleipnir-Technology/nidus-sync/db/models" "github.com/Gleipnir-Technology/nidus-sync/h3utils" + platformaddress "github.com/Gleipnir-Technology/nidus-sync/platform/address" "github.com/Gleipnir-Technology/nidus-sync/platform/types" "github.com/Gleipnir-Technology/nidus-sync/stadia" //"github.com/aarondl/opt/omit" @@ -86,7 +87,7 @@ func GeocodeRaw(ctx context.Context, org *models.Organization, address string) ( if err != nil { return nil, fmt.Errorf("client raw geocode failure on %s: %w", address, err) } - addresses, err := insertAddresses(ctx, db.PGInstance.BobDB, resp.Features) + addresses, err := platformaddress.InsertAddresses(ctx, db.PGInstance.PGXPool, resp.Features) if err != nil { return nil, fmt.Errorf("insert addresses: %w", err) } @@ -106,7 +107,7 @@ func GeocodeStructured(ctx context.Context, org *models.Organization, a types.Ad if err != nil { return nil, fmt.Errorf("client structured geocode failure on %s: %w", a.String(), err) } - addresses, err := insertAddresses(ctx, db.PGInstance.BobDB, resp.Features) + addresses, err := platformaddress.InsertAddresses(ctx, db.PGInstance.PGXPool, resp.Features) if err != nil { return nil, fmt.Errorf("insert addresses: %w", err) } @@ -139,7 +140,7 @@ func ReverseGeocode(ctx context.Context, location types.Location) (*GeocodeResul if err != nil { return nil, fmt.Errorf("client reverse geocode failure on %s: %w", location.String(), err) } - addresses, err := insertAddresses(ctx, db.PGInstance.BobDB, resp.Features) + addresses, err := platformaddress.InsertAddresses(ctx, db.PGInstance.PGXPool, resp.Features) if err != nil { return nil, fmt.Errorf("insert addresses: %w", err) } @@ -155,7 +156,7 @@ func ReverseGeocodeClosest(ctx context.Context, location types.Location) (*Geoco if err != nil { return nil, fmt.Errorf("client reverse geocode failure on %s: %w", location.String(), err) } - addresses, err := insertAddresses(ctx, db.PGInstance.BobDB, resp.Features) + addresses, err := platformaddress.InsertAddresses(ctx, db.PGInstance.PGXPool, resp.Features) if err != nil { return nil, fmt.Errorf("insert addresses: %w", err) } diff --git a/platform/image.go b/platform/image.go index 00a60e06..6e51fc83 100644 --- a/platform/image.go +++ b/platform/image.go @@ -13,16 +13,15 @@ import ( "math" "time" - "github.com/Gleipnir-Technology/bob" - "github.com/Gleipnir-Technology/bob/dialect/psql" - "github.com/Gleipnir-Technology/bob/dialect/psql/um" - "github.com/Gleipnir-Technology/nidus-sync/db/models" - "github.com/aarondl/opt/omit" - "github.com/aarondl/opt/omitnull" + "github.com/Gleipnir-Technology/nidus-sync/db" + "github.com/Gleipnir-Technology/nidus-sync/db/gen/nidus-sync/publicreport/model" + querypublicreport "github.com/Gleipnir-Technology/nidus-sync/db/query/publicreport" + "github.com/Gleipnir-Technology/nidus-sync/geomutil" "github.com/google/uuid" "github.com/rs/zerolog/log" "github.com/rwcarlsen/goexif/exif" "github.com/rwcarlsen/goexif/tiff" + "github.com/twpayne/go-geom" //exif "github.com/rwcarlsen/goexif/exif" //"github.com/dsoprea/go-exif-extra/format" ) @@ -87,49 +86,44 @@ func ImageExtractExif(content_type string, file_bytes []byte) (result *ExifColle return result, err } -func saveImageUploads(ctx context.Context, tx bob.Tx, uploads []ImageUpload) (models.PublicreportImageSlice, error) { - images := make(models.PublicreportImageSlice, 0) +func saveImageUploads(ctx context.Context, txn db.Ex, uploads []ImageUpload) ([]model.Image, error) { + images := make([]model.Image, 0) for _, u := range uploads { - image, err := models.PublicreportImages.Insert(&models.PublicreportImageSetter{ - ContentType: omit.From(u.ContentType), - - Created: omit.From(time.Now()), - //Location: psql.Raw("NULL"), - Location: omitnull.FromPtr[string](nil), - ResolutionX: omit.From(int32(u.Bounds.Max.X)), - ResolutionY: omit.From(int32(u.Bounds.Max.Y)), - StorageUUID: omit.From(u.UUID), - StorageSize: omit.From(int64(u.UploadFilesize)), - UploadedFilename: omit.From(u.UploadFilename), - }).One(ctx, tx) + var location *geom.T + if u.Exif != nil && u.Exif.GPS != nil && !(math.IsNaN(u.Exif.GPS.Longitude) || math.IsNaN(u.Exif.GPS.Latitude)) { + l := geomutil.PointFromLngLat(u.Exif.GPS.Longitude, u.Exif.GPS.Latitude) + location = &l + } + image := model.Image{ + // ID: + ContentType: u.ContentType, + Created: time.Now(), + Location: location, + ResolutionX: int32(u.Bounds.Max.X), + ResolutionY: int32(u.Bounds.Max.Y), + StorageUUID: u.UUID, + StorageSize: int64(u.UploadFilesize), + UploadedFilename: u.UploadFilename, + } + image, err := querypublicreport.ImageInsert(ctx, txn, image) if err != nil { return images, fmt.Errorf("Failed to create photo records: %w", err) } // TODO: figure out how to do this via the setter...? if u.Exif != nil { - if u.Exif.GPS != nil && !(math.IsNaN(u.Exif.GPS.Longitude) || math.IsNaN(u.Exif.GPS.Latitude)) { - _, err = psql.Update( - um.Table("publicreport.image"), - um.SetCol("location").To(fmt.Sprintf("ST_Point(%f, %f, 4326)", u.Exif.GPS.Longitude, u.Exif.GPS.Latitude)), - um.Where(psql.Quote("id").EQ(psql.Arg(image.ID))), - ).Exec(ctx, tx) - if err != nil { - return images, fmt.Errorf("set location: %w", err) - } - } - - exif_setters := make([]*models.PublicreportImageExifSetter, 0) + exif_models := make([]model.ImageExif, len(u.Exif.Tags)) + i := 0 for k, v := range u.Exif.Tags { to_save := trimQuotes(v) - exif_setters = append(exif_setters, &models.PublicreportImageExifSetter{ - ImageID: omit.From(image.ID), - Name: omit.From(k), - Value: omit.From(to_save), - }) + exif_models[i] = model.ImageExif{ + ImageID: image.ID, + Name: k, + Value: to_save, + } } - if len(exif_setters) > 0 { - _, err = models.PublicreportImageExifs.Insert(bob.ToMods(exif_setters...)).Exec(ctx, tx) + if len(exif_models) > 0 { + _, err = querypublicreport.ImageExifInserts(ctx, txn, exif_models) if err != nil { return images, fmt.Errorf("Failed to create photo exif records: %w", err) } diff --git a/platform/oauth.go b/platform/oauth.go index f611293b..2e8e5898 100644 --- a/platform/oauth.go +++ b/platform/oauth.go @@ -33,7 +33,7 @@ func GetOAuthForUser(ctx context.Context, user User) (*model.OAuthToken, error) } return nil, err } - return oauth, nil + return &oauth, nil } func HandleOauthAccessCode(ctx context.Context, user User, code string) error { @@ -66,6 +66,6 @@ func HandleOauthAccessCode(ctx context.Context, user User, code string) error { if err != nil { return fmt.Errorf("Failed to save token to database: %w", err) } - go updateArcgisUserData(context.Background(), user.model, oauth) + go updateArcgisUserData(context.Background(), user.model, &oauth) return nil } diff --git a/platform/oauth/oauth.go b/platform/oauth/oauth.go index e17f174f..0619974c 100644 --- a/platform/oauth/oauth.go +++ b/platform/oauth/oauth.go @@ -102,7 +102,7 @@ func GetOAuthForOrg(ctx context.Context, org *models.Organization) (*model.OAuth return nil, fmt.Errorf("Failed to query all oauth tokens for org: %w", err) } for _, oauth := range oauths { - return oauth, nil + return &oauth, nil } } return nil, nil @@ -125,7 +125,7 @@ func RefreshAccessToken(ctx context.Context, oauth *model.OAuthToken) error { AccessTokenExpires: accessExpires, Username: token.Username, } - err = queryarcgis.OAuthTokenUpdateAccessToken(ctx, int64(oauth.ID), &model) + err = queryarcgis.OAuthTokenUpdateAccessToken(ctx, int64(oauth.ID), model) if err != nil { return fmt.Errorf("Failed to update oauth in database: %w", err) } @@ -152,7 +152,7 @@ func RefreshRefreshToken(ctx context.Context, oauth *model.OAuthToken) error { RefreshTokenExpires: refreshExpires, Username: token.Username, } - err = queryarcgis.OAuthTokenUpdateRefreshToken(ctx, int64(oauth.ID), &model) + err = queryarcgis.OAuthTokenUpdateRefreshToken(ctx, int64(oauth.ID), model) if err != nil { return fmt.Errorf("Failed to update oauth in database: %w", err) } diff --git a/platform/publicreport.go b/platform/publicreport.go index 577d2609..e79a6e78 100644 --- a/platform/publicreport.go +++ b/platform/publicreport.go @@ -9,26 +9,20 @@ import ( "strings" "time" - "github.com/Gleipnir-Technology/bob" - "github.com/Gleipnir-Technology/bob/dialect/psql" - "github.com/Gleipnir-Technology/bob/dialect/psql/sm" - "github.com/Gleipnir-Technology/bob/dialect/psql/um" "github.com/Gleipnir-Technology/nidus-sync/db" - "github.com/Gleipnir-Technology/nidus-sync/db/enums" "github.com/Gleipnir-Technology/nidus-sync/db/gen/nidus-sync/public/model" + tablepublic "github.com/Gleipnir-Technology/nidus-sync/db/gen/nidus-sync/public/table" modelpublicreport "github.com/Gleipnir-Technology/nidus-sync/db/gen/nidus-sync/publicreport/model" - "github.com/Gleipnir-Technology/nidus-sync/db/models" + tablepublicreport "github.com/Gleipnir-Technology/nidus-sync/db/gen/nidus-sync/publicreport/table" querypublic "github.com/Gleipnir-Technology/nidus-sync/db/query/public" querypublicreport "github.com/Gleipnir-Technology/nidus-sync/db/query/publicreport" - "github.com/aarondl/opt/omit" - "github.com/aarondl/opt/omitnull" - //"github.com/Gleipnir-Technology/nidus-sync/platform/background" "github.com/Gleipnir-Technology/nidus-sync/platform/email" "github.com/Gleipnir-Technology/nidus-sync/platform/event" "github.com/Gleipnir-Technology/nidus-sync/platform/geocode" "github.com/Gleipnir-Technology/nidus-sync/platform/publicreport" "github.com/Gleipnir-Technology/nidus-sync/platform/text" "github.com/Gleipnir-Technology/nidus-sync/platform/types" + "github.com/go-jet/jet/v2/postgres" "github.com/rs/zerolog/log" ) @@ -86,7 +80,7 @@ func PublicReportByIDWater(ctx context.Context, report_id string, is_public bool return publicreport.ByIDWater(ctx, report_id, is_public) } func PublicReportInvalid(ctx context.Context, user User, public_id string) error { - report, err := publicReportFromID(ctx, public_id) + report, err := querypublicreport.ReportFromPublicID(ctx, db.PGInstance.PGXPool, public_id) if err != nil { return fmt.Errorf("query report existence: %w", err) } @@ -94,11 +88,16 @@ func PublicReportInvalid(ctx context.Context, user User, public_id string) error return fmt.Errorf("user is from a different organization") } - err = report.Update(ctx, db.PGInstance.BobDB, &models.PublicreportReportSetter{ - Reviewed: omitnull.From(time.Now()), - ReviewerID: omitnull.From(int32(user.ID)), - Status: omit.From(enums.PublicreportReportstatustypeInvalidated), - }) + now := time.Now() + report_updater := querypublicreport.ReportUpdater{} + report_updater.Model.Reviewed = &now + report_updater.Set(tablepublicreport.Report.Reviewed) + reporter_id := int32(user.ID) + report_updater.Model.ReviewerID = &reporter_id + report_updater.Set(tablepublicreport.Report.ReviewerID) + report_updater.Model.Status = modelpublicreport.Reportstatustype_Invalidated + report_updater.Set(tablepublicreport.Report.Status) + err = report_updater.Execute(ctx, db.PGInstance.PGXPool, report.ID) log.Info().Int32("id", report.ID).Msg("Report marked as invalid") event.Updated(event.TypeRMOPublicReport, user.Organization.ID, public_id) @@ -112,7 +111,7 @@ func PublicReportMessageCreate(ctx context.Context, user User, public_id, messag } defer txn.Rollback(ctx) - report, err := publicReportFromID(ctx, public_id) + report, err := querypublicreport.ReportFromPublicID(ctx, db.PGInstance.PGXPool, public_id) if err != nil { return nil, fmt.Errorf("query report existence: %w", err) } @@ -144,76 +143,72 @@ func PublicReportMessageCreate(ctx context.Context, user User, public_id, messag return nil, errors.New("no contact methods available") } } -func PublicReportUpdateCompliance(ctx context.Context, public_id string, report_setter *models.PublicreportReportSetter, compliance_setter *models.PublicreportComplianceSetter, address *types.Address, location *types.Location) (*types.PublicReportCompliance, error) { - txn, err := db.PGInstance.BobDB.BeginTx(ctx, nil) +func PublicReportUpdateCompliance(ctx context.Context, public_id string, report_updates querypublicreport.ReportUpdater, compliance_updates querypublicreport.ComplianceUpdater, address *types.Address, location *types.Location) error { + //txn, err := db.PGInstance.BobDB.BeginTx(ctx, nil) + txn, err := db.BeginTxn(ctx) if err != nil { - return nil, fmt.Errorf("create txn: %w", err) + return fmt.Errorf("create txn: %w", err) } defer txn.Rollback(ctx) - report, err := publicReportFromID(ctx, public_id) + report, err := querypublicreport.ReportFromPublicID(ctx, db.PGInstance.PGXPool, public_id) if err != nil { - return nil, fmt.Errorf("query report existence: %w", err) + return fmt.Errorf("query report existence: %w", err) } - compliance, err := models.FindPublicreportCompliance(ctx, txn, report.ID) + //compliance, err := models.FindPublicreportCompliance(ctx, txn, report.ID) + compliance, err := querypublicreport.ComplianceFromID(ctx, txn, int64(report.ID)) if err != nil { - return nil, fmt.Errorf("find compliance %d: %w", report.ID, err) + return fmt.Errorf("find compliance %d: %w", report.ID, err) } // Don't allow modifying of the submission date if it's set - if compliance_setter.Submitted.IsValue() { - if compliance.Submitted.IsValue() { - compliance_setter.Submitted.Unset() + if compliance_updates.Has(tablepublicreport.Compliance.Submitted) { + if compliance.Submitted != nil { + compliance_updates.Unset(tablepublicreport.Compliance.Submitted) } else { - comm := &model.Communication{ + comm := model.Communication{ OrganizationID: report.OrganizationID, SourceReportID: &report.ID, } - comm, err := querypublic.CommunicationInsert(ctx, txn, comm) + comm, err = querypublic.CommunicationInsert(ctx, txn, comm) if err != nil { - return nil, fmt.Errorf("insert communication: %w", err) + return fmt.Errorf("insert communication: %w", err) + } + comm_log := model.CommunicationLogEntry{ + CommunicationID: comm.ID, + Created: time.Now(), + Type: model.Communicationlogentry_Created, + User: nil, + } + comm_log, err = querypublic.CommunicationLogEntryInsert(ctx, txn, comm_log) + if err != nil { + return fmt.Errorf("insert communication log entry: %w", err) } log.Debug().Int32("id", comm.ID).Msg("inserted new communication") } } // Avoid attempting to perform an empty update - if report_setter.LatlngAccuracyValue.IsValue() || - report_setter.ReporterEmail.IsValue() || - report_setter.ReporterName.IsValue() || - report_setter.ReporterPhone.IsValue() { - err = report.Update(ctx, txn, report_setter) - if err != nil { - return nil, fmt.Errorf("update report: %w", err) - } + err = report_updates.Execute(ctx, txn, int64(report.ID)) + if err != nil { + return fmt.Errorf("update report: %w", err) } - // Avoid attempting to perform an empty update - if compliance_setter.AccessInstructions.IsValue() || - compliance_setter.AvailabilityNotes.IsValue() || - compliance_setter.Comments.IsValue() || - compliance_setter.GateCode.IsValue() || - compliance_setter.HasDog.IsValue() || - compliance_setter.PermissionType.IsValue() || - compliance_setter.ReportPhoneCanText.IsValue() || - compliance_setter.Submitted.IsValue() || - compliance_setter.WantsScheduled.IsValue() { - err = compliance.Update(ctx, txn, compliance_setter) - if err != nil { - return nil, fmt.Errorf("update compliance: %w", err) - } + err = compliance_updates.Execute(ctx, txn, int64(compliance.ReportID)) + if err != nil { + return fmt.Errorf("update compliance: %w", err) } if address != nil { err = publicReportUpdateAddress(ctx, txn, report, *address) if err != nil { - return nil, fmt.Errorf("update address: %w", err) + return fmt.Errorf("update address: %w", err) } } if location != nil { err = publicReportUpdateLocation(ctx, txn, report.ID, *location) if err != nil { - return nil, fmt.Errorf("update location: %w", err) + return fmt.Errorf("update location: %w", err) } } txn.Commit(ctx) - return publicreport.ByIDCompliance(ctx, public_id, false) + return nil } func PublicReportReporterUpdated(ctx context.Context, org_id int32, report_id string) { event.Updated(event.TypeRMOPublicReport, org_id, report_id) @@ -221,13 +216,13 @@ func PublicReportReporterUpdated(ctx context.Context, org_id int32, report_id st func PublicReportsForOrganization(ctx context.Context, org_id int32, is_public bool) ([]*types.PublicReport, error) { return publicreport.ReportsForOrganization(ctx, org_id, is_public) } -func PublicReportsFromIDs(ctx context.Context, report_ids []int64) ([]*modelpublicreport.Report, error) { - return querypublicreport.PublicReportsFromIDs(ctx, report_ids) +func PublicReportsFromIDs(ctx context.Context, report_ids []int64) ([]modelpublicreport.Report, error) { + return querypublicreport.ReportsFromIDs(ctx, report_ids) } -func PublicReportComplianceCreate(ctx context.Context, setter_report models.PublicreportReportSetter, setter_compliance models.PublicreportComplianceSetter, org_id int32) (*models.PublicreportReport, error) { - return publicReportCreate(ctx, setter_report, nil, nil, nil, org_id, func(ctx context.Context, txn bob.Executor, report_id int32) error { - setter_compliance.ReportID = omit.From(report_id) - _, err := models.PublicreportCompliances.Insert(&setter_compliance).One(ctx, txn) +func PublicReportComplianceCreate(ctx context.Context, setter_report modelpublicreport.Report, setter_compliance modelpublicreport.Compliance, org_id int32) (modelpublicreport.Report, error) { + return publicReportCreate(ctx, setter_report, nil, nil, nil, org_id, func(ctx context.Context, txn db.Ex, report_id int32) error { + setter_compliance.ReportID = report_id + _, err := querypublicreport.ComplianceInsert(ctx, txn, setter_compliance) if err != nil { return fmt.Errorf("Failed to create nuisance database record: %w", err) } @@ -235,13 +230,13 @@ func PublicReportComplianceCreate(ctx context.Context, setter_report models.Publ }) } func PublicReportImageCreate(ctx context.Context, public_id string, images []ImageUpload) error { - txn, err := db.PGInstance.BobDB.BeginTx(ctx, nil) + txn, err := db.BeginTxn(ctx) if err != nil { return fmt.Errorf("create txn: %w", err) } defer txn.Rollback(ctx) - report, err := publicReportFromID(ctx, public_id) + report, err := querypublicreport.ReportFromPublicID(ctx, db.PGInstance.PGXPool, public_id) if err != nil { return fmt.Errorf("report from ID: %w", err) } @@ -250,14 +245,14 @@ func PublicReportImageCreate(ctx context.Context, public_id string, images []Ima return fmt.Errorf("Failed to save image uploads: %w", err) } if len(saved_images) > 0 { - setters := make([]*models.PublicreportReportImageSetter, 0) - for _, image := range saved_images { - setters = append(setters, &models.PublicreportReportImageSetter{ - ImageID: omit.From(int32(image.ID)), - ReportID: omit.From(int32(report.ID)), - }) + report_images := make([]modelpublicreport.ReportImage, len(saved_images)) + for i, image := range saved_images { + report_images[i] = modelpublicreport.ReportImage{ + ImageID: image.ID, + ReportID: report.ID, + } } - _, err = models.PublicreportReportImages.Insert(bob.ToMods(setters...)).Exec(ctx, txn) + _, err := querypublicreport.ReportImagesInsert(ctx, txn, report_images) if err != nil { return fmt.Errorf("Failed to save reference to images: %w", err) } @@ -266,10 +261,10 @@ func PublicReportImageCreate(ctx context.Context, public_id string, images []Ima txn.Commit(ctx) return nil } -func PublicReportNuisanceCreate(ctx context.Context, setter_report models.PublicreportReportSetter, setter_nuisance models.PublicreportNuisanceSetter, location types.Location, address Address, images []ImageUpload) (*models.PublicreportReport, error) { - return publicReportCreate(ctx, setter_report, &location, &address, images, 0, func(ctx context.Context, txn bob.Executor, report_id int32) error { - setter_nuisance.ReportID = omit.From(report_id) - _, err := models.PublicreportNuisances.Insert(&setter_nuisance).One(ctx, txn) +func PublicReportNuisanceCreate(ctx context.Context, setter_report modelpublicreport.Report, setter_nuisance modelpublicreport.Nuisance, location types.Location, address Address, images []ImageUpload) (modelpublicreport.Report, error) { + return publicReportCreate(ctx, setter_report, &location, &address, images, 0, func(ctx context.Context, txn db.Ex, report_id int32) error { + setter_nuisance.ReportID = report_id + _, err := querypublicreport.NuisanceInsert(ctx, txn, setter_nuisance) if err != nil { return fmt.Errorf("Failed to create nuisance database record: %w", err) } @@ -277,10 +272,10 @@ func PublicReportNuisanceCreate(ctx context.Context, setter_report models.Public }) } -func PublicReportWaterCreate(ctx context.Context, setter_report models.PublicreportReportSetter, setter_water models.PublicreportWaterSetter, location types.Location, address Address, images []ImageUpload) (*models.PublicreportReport, error) { - return publicReportCreate(ctx, setter_report, &location, &address, images, 0, func(ctx context.Context, txn bob.Executor, report_id int32) error { - setter_water.ReportID = omit.From(report_id) - _, err := models.PublicreportWaters.Insert(&setter_water).One(ctx, txn) +func PublicReportWaterCreate(ctx context.Context, setter_report modelpublicreport.Report, setter_water modelpublicreport.Water, location types.Location, address Address, images []ImageUpload) (modelpublicreport.Report, error) { + return publicReportCreate(ctx, setter_report, &location, &address, images, 0, func(ctx context.Context, txn db.Ex, report_id int32) error { + setter_water.ReportID = report_id + _, err := querypublicreport.WaterInsert(ctx, txn, setter_water) if err != nil { return fmt.Errorf("Failed to create water database record: %w", err) } @@ -288,56 +283,52 @@ func PublicReportWaterCreate(ctx context.Context, setter_report models.Publicrep }) } func PublicReportTypeByID(ctx context.Context, public_id string) (string, error) { - report, err := models.PublicreportReports.Query( - models.SelectWhere.PublicreportReports.PublicID.EQ(public_id), - ).One(ctx, db.PGInstance.BobDB) + report, err := querypublicreport.ReportFromPublicID(ctx, db.PGInstance.PGXPool, public_id) if err != nil { return "", fmt.Errorf("query report '%s': %w", public_id, err) } return report.ReportType.String(), nil } -type funcSetReportDetail = func(context.Context, bob.Executor, int32) error +type funcSetReportDetail = func(context.Context, db.Ex, int32) error -func publicReportCreate(ctx context.Context, setter_report models.PublicreportReportSetter, location *types.Location, address *Address, images []ImageUpload, organization_id int32, detail_setter funcSetReportDetail) (result *models.PublicreportReport, err error) { - txn, err := db.PGInstance.BobDB.BeginTx(ctx, nil) +func publicReportCreate(ctx context.Context, setter_report modelpublicreport.Report, location *types.Location, address *Address, images []ImageUpload, organization_id int32, detail_setter funcSetReportDetail) (result modelpublicreport.Report, err error) { + txn, err := db.BeginTxn(ctx) if err != nil { - return nil, fmt.Errorf("create txn: %w", err) + return result, fmt.Errorf("create txn: %w", err) } defer txn.Rollback(ctx) - if setter_report.PublicID.IsUnset() { + if setter_report.PublicID == "" { public_id, err := GenerateReportID() if err != nil { - return nil, fmt.Errorf("create public ID: %w", err) + return result, fmt.Errorf("create public ID: %w", err) } - setter_report.PublicID = omit.From(public_id) + setter_report.PublicID = public_id } - var addr *models.Address + var addr *types.Address if address != nil { if address.GID != "" { - addr, err = geocode.EnsureAddress(ctx, txn, *address) + addr_existing, err := geocode.EnsureAddress(ctx, txn, *address) if err != nil { - return nil, fmt.Errorf("Failed to ensure address: %w", err) + return result, fmt.Errorf("Failed to ensure address: %w", err) } + addr = &addr_existing } else if address.Raw != "" { geo_res, err := geocode.GeocodeRaw(ctx, nil, address.Raw) if err != nil { - return nil, fmt.Errorf("Failed to geocode raw: %w", err) - } - addr, err = models.FindAddress(ctx, txn, *geo_res.Address.ID) - if err != nil { - return nil, fmt.Errorf("Failed to lookup address: %w", err) + return result, fmt.Errorf("Failed to geocode raw: %w", err) } + addr = &geo_res.Address } else { - return nil, fmt.Errorf("empty address") + return result, fmt.Errorf("empty address") } } saved_images, err := saveImageUploads(ctx, txn, images) if err != nil { - return nil, fmt.Errorf("Failed to save image uploads: %w", err) + return result, fmt.Errorf("Failed to save image uploads: %w", err) } if organization_id == 0 { organization_id, err = matchDistrict(ctx, location, images, addr) @@ -345,14 +336,14 @@ func publicReportCreate(ctx context.Context, setter_report models.PublicreportRe log.Warn().Err(err).Msg("Failed to match district") } } - setter_report.OrganizationID = omit.From(organization_id) + setter_report.OrganizationID = organization_id if addr != nil { - setter_report.AddressID = omitnull.From(addr.ID) + setter_report.AddressID = addr.ID } - result, err = models.PublicreportReports.Insert(&setter_report).One(ctx, txn) + result, err = querypublicreport.ReportInsert(ctx, txn, setter_report) if err != nil { - return nil, fmt.Errorf("Failed to create report database record: %w", err) + return result, fmt.Errorf("Failed to create report database record: %w", err) } if location != nil { l := *location @@ -360,48 +351,48 @@ func publicReportCreate(ctx context.Context, setter_report models.PublicreportRe publicReportUpdateLocation(ctx, txn, result.ID, l) } } - log.Info().Str("public_id", setter_report.PublicID.GetOr("")).Int32("id", result.ID).Msg("Created base report") + log.Info().Str("public_id", setter_report.PublicID).Int32("id", result.ID).Msg("Created base report") if len(saved_images) > 0 { - setters := make([]*models.PublicreportReportImageSetter, 0) - for _, image := range saved_images { - setters = append(setters, &models.PublicreportReportImageSetter{ - ImageID: omit.From(int32(image.ID)), - ReportID: omit.From(int32(result.ID)), - }) + setters := make([]modelpublicreport.ReportImage, len(saved_images)) + for i, image := range saved_images { + setters[i] = modelpublicreport.ReportImage{ + ImageID: int32(image.ID), + ReportID: int32(result.ID), + } } - _, err = models.PublicreportReportImages.Insert(bob.ToMods(setters...)).Exec(ctx, txn) + _, err = querypublicreport.ReportImagesInsert(ctx, txn, setters) if err != nil { - return nil, fmt.Errorf("Failed to save reference to images: %w", err) + return result, fmt.Errorf("Failed to save reference to images: %w", err) } log.Info().Int("len", len(images)).Msg("saved uploaded images") } err = detail_setter(ctx, txn, result.ID) if err != nil { - return nil, fmt.Errorf("detail setter: %w", err) + return result, fmt.Errorf("detail setter: %w", err) } - models.PublicreportReportLogs.Insert(&models.PublicreportReportLogSetter{ - Created: omit.From(time.Now()), - EmailLogID: omitnull.FromPtr[int32](nil), + _, err = querypublicreport.ReportLogInsert(ctx, txn, modelpublicreport.ReportLog{ + Created: time.Now(), + EmailLogID: nil, // ID - ReportID: omit.From(result.ID), - TextLogID: omitnull.FromPtr[int32](nil), - Type: omit.From(enums.PublicreportReportlogtypeCreated), - UserID: omitnull.FromPtr[int32](nil), - }).One(ctx, txn) + ReportID: result.ID, + TextLogID: nil, + Type: modelpublicreport.Reportlogtype_Created, + UserID: nil, + }) // Only create communication entries for compliance when they're submitted - report_type := setter_report.ReportType.MustGet() - if report_type != enums.PublicreportReporttypeCompliance { - comm := &model.Communication{ + report_type := setter_report.ReportType + if report_type != modelpublicreport.Reporttype_Compliance { + comm := model.Communication{ OrganizationID: result.OrganizationID, SourceReportID: &result.ID, } comm, err = querypublic.CommunicationInsert(ctx, txn, comm) if err != nil { - return nil, fmt.Errorf("insert communication: %w", err) + return result, fmt.Errorf("insert communication: %w", err) } log.Debug().Int32("id", comm.ID).Msg("inserted new communication") } @@ -415,49 +406,55 @@ func publicReportCreate(ctx context.Context, setter_report models.PublicreportRe ) return result, nil } -func publicReportFromID(ctx context.Context, public_id string) (*models.PublicreportReport, error) { - report, err := models.PublicreportReports.Query( - models.SelectWhere.PublicreportReports.PublicID.EQ(public_id), - ).One(ctx, db.PGInstance.BobDB) - if err != nil { - return nil, err - } - return report, nil -} -func publicReportUpdateAddress(ctx context.Context, txn bob.Executor, report *models.PublicreportReport, address types.Address) error { - err := report.Update(ctx, txn, &models.PublicreportReportSetter{ - AddressGid: omit.From(address.GID), - AddressRaw: omit.From(address.Raw), - }) +func publicReportUpdateAddress(ctx context.Context, txn db.Tx, report *modelpublicreport.Report, address types.Address) error { + statement := tablepublicreport.Report.UPDATE( + tablepublicreport.Report.AddressGid, + tablepublicreport.Report.AddressRaw, + ).SET( + postgres.String(address.GID), + postgres.String(address.Raw), + ).FROM(tablepublic.Address). + WHERE( + tablepublicreport.Report.ID.EQ(postgres.Int(int64(report.ID))), + ) + err := db.ExecuteNoneTx(ctx, txn, statement) + if err != nil { return fmt.Errorf("update report: %w", err) } - _, err = psql.Update( - um.Table("publicreport.report"), - um.SetCol("address_id").To( - psql.Select( - sm.Columns("id"), - sm.From("address"), - sm.Where(psql.Quote("gid").EQ(psql.Arg(address.GID))), - sm.Limit(1), - ), - ), - um.Where(psql.Quote("publicreport", "report", "id").EQ(psql.Arg(report.ID))), - ).Exec(ctx, txn) + statement = tablepublicreport.Report.UPDATE( + tablepublicreport.Report.AddressID, + ).SET( + tablepublic.Address.SELECT( + tablepublic.Address.ID, + ).WHERE( + tablepublic.Address.Gid.EQ(postgres.String(address.GID)), + ).LIMIT(1), + ).WHERE( + tablepublicreport.Report.ID.EQ(postgres.Int(int64(report.ID))), + ) + err = db.ExecuteNoneTx(ctx, txn, statement) if err != nil { return fmt.Errorf("update report address_id: %w", err) } return nil } -func publicReportUpdateLocation(ctx context.Context, txn bob.Executor, id int32, location types.Location) error { +func publicReportUpdateLocation(ctx context.Context, txn db.Tx, id int32, location types.Location) error { h3cell, _ := location.H3Cell() + if h3cell == nil { + return fmt.Errorf("nil h3 cell") + } geom_query, _ := location.GeometryQuery() - _, err := psql.Update( - um.Table("publicreport.report"), - um.SetCol("h3cell").ToArg(h3cell), - um.SetCol("location").To(geom_query), - um.Where(psql.Quote("id").EQ(psql.Arg(id))), - ).Exec(ctx, txn) + statement := tablepublicreport.Report.UPDATE( + tablepublicreport.Report.H3cell, + tablepublicreport.Report.Location, + ).SET( + postgres.Int(int64(*h3cell)), + postgres.Raw(geom_query), + ).WHERE( + tablepublicreport.Report.ID.EQ(postgres.Int(int64(id))), + ) + err := db.ExecuteNoneTx(ctx, txn, statement) if err != nil { return fmt.Errorf("Failed to insert publicreport.report geospatial", err) } diff --git a/platform/publicreport/address.go b/platform/publicreport/address.go index c480685f..ab4f7be0 100644 --- a/platform/publicreport/address.go +++ b/platform/publicreport/address.go @@ -4,21 +4,18 @@ import ( "context" "fmt" - "github.com/Gleipnir-Technology/bob" - //"github.com/Gleipnir-Technology/bob/dialect/psql" - "github.com/Gleipnir-Technology/nidus-sync/db/models" + "github.com/Gleipnir-Technology/nidus-sync/db" + querypublic "github.com/Gleipnir-Technology/nidus-sync/db/query/public" "github.com/Gleipnir-Technology/nidus-sync/platform/types" ) -func loadAddresses(ctx context.Context, txn bob.Executor, address_ids []int32) (results map[int32]types.Address, err error) { - rows, err := models.Addresses.Query( - models.SelectWhere.Addresses.ID.In(address_ids...), - ).All(ctx, txn) +func loadAddresses(ctx context.Context, txn db.Tx, address_ids []int64) (results map[int32]types.Address, err error) { + addresses, err := querypublic.AddressesFromIDs(ctx, txn, address_ids) if err != nil { return nil, fmt.Errorf("query addresses: %w", err) } - results = make(map[int32]types.Address, len(rows)) - for _, row := range rows { + results = make(map[int32]types.Address, len(addresses)) + for _, row := range addresses { results[row.ID] = types.AddressFromModel(row) } return results, nil diff --git a/platform/signal.go b/platform/signal.go index 9811a4d1..b1899392 100644 --- a/platform/signal.go +++ b/platform/signal.go @@ -11,19 +11,19 @@ import ( "github.com/Gleipnir-Technology/bob/dialect/psql" "github.com/Gleipnir-Technology/bob/dialect/psql/im" "github.com/Gleipnir-Technology/bob/dialect/psql/sm" - "github.com/Gleipnir-Technology/bob/dialect/psql/um" "github.com/Gleipnir-Technology/nidus-sync/db" - "github.com/Gleipnir-Technology/nidus-sync/db/enums" - "github.com/Gleipnir-Technology/nidus-sync/db/models" + modelpublic "github.com/Gleipnir-Technology/nidus-sync/db/gen/nidus-sync/public/model" + modelpublicreport "github.com/Gleipnir-Technology/nidus-sync/db/gen/nidus-sync/publicreport/model" + tablepublicreport "github.com/Gleipnir-Technology/nidus-sync/db/gen/nidus-sync/publicreport/table" + querypublic "github.com/Gleipnir-Technology/nidus-sync/db/query/public" + querypublicreport "github.com/Gleipnir-Technology/nidus-sync/db/query/publicreport" + "github.com/Gleipnir-Technology/nidus-sync/geomutil" "github.com/Gleipnir-Technology/nidus-sync/platform/event" "github.com/Gleipnir-Technology/nidus-sync/platform/publicreport" "github.com/Gleipnir-Technology/nidus-sync/platform/types" - //"github.com/Gleipnir-Technology/nidus-sync/platform/geocode" - //"github.com/Gleipnir-Technology/nidus-sync/platform/geom" - "github.com/aarondl/opt/omit" - "github.com/aarondl/opt/omitnull" "github.com/rs/zerolog/log" "github.com/stephenafamo/scan" + "github.com/twpayne/go-geom" ) type Signal struct { @@ -113,16 +113,13 @@ func SignalCreateFromPool(ctx context.Context, txn bob.Executor, user User, site // Create a lead from the given signal and site func SignalCreateFromPublicreport(ctx context.Context, user User, report_id string) (*int32, error) { - txn, err := db.PGInstance.BobDB.BeginTx(ctx, nil) + txn, err := db.BeginTxn(ctx) defer txn.Rollback(ctx) if err != nil { return nil, fmt.Errorf("start transaction: %w", err) } - report, err := models.PublicreportReports.Query( - models.SelectWhere.PublicreportReports.PublicID.EQ(report_id), - models.SelectWhere.PublicreportReports.OrganizationID.EQ(user.Organization.ID), - ).One(ctx, txn) + report, err := querypublicreport.ReportFromPublicIDForOrg(ctx, txn, report_id, int64(user.Organization.ID)) if err != nil { return nil, fmt.Errorf("query report existence: %w", err) } @@ -130,33 +127,31 @@ func SignalCreateFromPublicreport(ctx context.Context, user User, report_id stri // At this point we have a report. We need to decide where to put it based on either the address or // the location. var site_id int32 - var location string - if report.AddressID.IsValue() { - address_id := report.AddressID.MustGet() - address, err := models.FindAddress(ctx, txn, address_id) + var location geom.T + if report.AddressID != nil { + address_id := *report.AddressID + address, err := querypublic.AddressFromID(ctx, txn, int64(address_id)) if err != nil { return nil, fmt.Errorf("find address: %w", err) } - site, err := siteFromAddress(ctx, txn, user, address_id) + site, err := querypublic.SiteFromAddressIDForOrg(ctx, txn, int64(address_id), int64(user.Organization.ID)) if err != nil { return nil, fmt.Errorf("site from address: %w", err) } site_id = site.ID - lat := address.LocationLatitude.GetOr(0.0) - lng := address.LocationLongitude.GetOr(0.0) - location = fmt.Sprintf("POINT(%f %f)", lng, lat) - } else if report.LocationLatitude.IsValue() && report.LocationLongitude.IsValue() { - lat := report.LocationLatitude.MustGet() - lng := report.LocationLongitude.MustGet() + location = geomutil.PointFromLngLat(*address.LocationLongitude, *address.LocationLatitude) + } else if report.LocationLatitude != nil && report.LocationLongitude != nil { + lat := report.LocationLatitude + lng := report.LocationLongitude site, err := siteFromLocation(ctx, txn, user, types.Location{ - Latitude: lat, - Longitude: lng, + Latitude: *lat, + Longitude: *lng, }) if err != nil { return nil, fmt.Errorf("site from address: %w", err) } site_id = site.ID - location = fmt.Sprintf("POINT(%f %f)", lng, lat) + location = geomutil.PointFromLngLat(*lng, *lat) } else if report.AddressRaw != "" { // At this point we don't have an address, and we don't have GPS // We'll try geocoding and creating an address from that. @@ -164,54 +159,57 @@ func SignalCreateFromPublicreport(ctx context.Context, user User, report_id stri if err != nil { return nil, fmt.Errorf("site from address: %w", err) } - address, err := models.FindAddress(ctx, txn, site.AddressID) + address, err := querypublic.AddressFromID(ctx, txn, int64(site.AddressID)) if err != nil { return nil, fmt.Errorf("find address from raw: %w", err) } site_id = site.ID - lat := address.LocationLatitude.GetOr(0.0) - lng := address.LocationLongitude.GetOr(0.0) - location = fmt.Sprintf("POINT(%f %f)", lng, lat) + lat := address.LocationLatitude + lng := address.LocationLongitude + location = geomutil.PointFromLngLat(*lng, *lat) } else { // We have no structured address, no GPS, no unstructued address. // There's really nothing we can make this lead from and have it be meaningful return nil, errors.New("Refusing to create a signal with no location data.") } - var signal_type enums.Signaltype + var signal_type modelpublic.Signaltype switch report.ReportType { - case enums.PublicreportReporttypeNuisance: - signal_type = enums.SignaltypePublicreportNuisance - case enums.PublicreportReporttypeWater: - signal_type = enums.SignaltypePublicreportWater + case modelpublicreport.Reporttype_Nuisance: + signal_type = modelpublic.Signaltype_PublicreportNuisance + case modelpublicreport.Reporttype_Water: + signal_type = modelpublic.Signaltype_PublicreportWater default: return nil, fmt.Errorf("Unrecognized report type %s", string(report.ReportType)) } - log.Debug().Str("location", location).Msg("inserting signal") - signal, err := models.Signals.Insert(&models.SignalSetter{ - Addressed: omitnull.FromPtr[time.Time](nil), - Addressor: omitnull.FromPtr[int32](nil), - Created: omit.From(time.Now()), - Creator: omit.From(int32(user.ID)), - FeaturePoolFeatureID: omitnull.FromPtr[int32](nil), + signal := modelpublic.Signal{ + Addressed: nil, + Addressor: nil, + Created: time.Now(), + Creator: int32(user.ID), + FeaturePoolFeatureID: nil, // ID - OrganizationID: omit.From(int32(user.Organization.ID)), - Location: omit.From(location), - ReportID: omitnull.From(report.ID), - Species: omitnull.FromPtr[enums.Mosquitospecies](nil), - SiteID: omitnull.From(site_id), - Type: omit.From[enums.Signaltype](signal_type), - }).One(ctx, txn) + OrganizationID: int32(user.Organization.ID), + Location: location, + ReportID: &report.ID, + Species: nil, + SiteID: &site_id, + Type: signal_type, + } + signal, err = querypublic.SignalInsert(ctx, txn, signal) if err != nil { return nil, fmt.Errorf("create signal: %w", err) } - _, err = psql.Update( - um.Table(psql.Quote("publicreport", "report")), - um.SetCol("reviewed").ToArg(time.Now()), - um.SetCol("reviewer_id").ToArg(user.ID), - um.SetCol("status").ToArg(enums.PublicreportReportstatustypeReviewed), - um.Where(psql.Quote("public_id").EQ(psql.Arg(report_id))), - ).Exec(ctx, txn) + report_updater := querypublicreport.ReportUpdater{} + now := time.Now() + report_updater.Model.Reviewed = &now + report_updater.Set(tablepublicreport.Report.Reviewed) + user_id := int32(user.ID) + report_updater.Model.ReviewerID = &user_id + report_updater.Set(tablepublicreport.Report.ReviewerID) + report_updater.Model.Status = modelpublicreport.Reportstatustype_Reviewed + report_updater.Set(tablepublicreport.Report.Status) + err = report_updater.Execute(ctx, txn, report_id) if err != nil { return nil, fmt.Errorf("failed to update report %d: %w", report_id, err) } diff --git a/platform/site.go b/platform/site.go index 7e122046..cb567a61 100644 --- a/platform/site.go +++ b/platform/site.go @@ -12,7 +12,9 @@ import ( "github.com/Gleipnir-Technology/bob/dialect/psql/sm" "github.com/Gleipnir-Technology/bob/types/pgtypes" "github.com/Gleipnir-Technology/nidus-sync/db" + "github.com/Gleipnir-Technology/nidus-sync/db/gen/nidus-sync/public/model" "github.com/Gleipnir-Technology/nidus-sync/db/models" + querypublic "github.com/Gleipnir-Technology/nidus-sync/db/query/public" nhttp "github.com/Gleipnir-Technology/nidus-sync/http" "github.com/Gleipnir-Technology/nidus-sync/platform/geocode" "github.com/Gleipnir-Technology/nidus-sync/platform/types" @@ -101,20 +103,7 @@ func SitesByID(ctx context.Context, ids []int32) (map[int32]*models.Site, error) } return results, err } -func siteFromAddress(ctx context.Context, txn bob.Tx, user User, address_id int32) (*models.Site, error) { - site, err := models.Sites.Query( - models.SelectWhere.Sites.AddressID.EQ(address_id), - models.SelectWhere.Sites.OrganizationID.EQ(user.Organization.ID), - ).One(ctx, txn) - if err == nil { - return site, nil - } - if err.Error() != "sql: no rows in result set" { - return nil, fmt.Errorf("query site: %w", err) - } - return SiteCreate(ctx, txn, user, address_id) -} -func siteFromAddressRaw(ctx context.Context, txn bob.Tx, user User, address string) (*models.Site, error) { +func siteFromAddressRaw(ctx context.Context, txn db.Ex, user User, address string) (*model.Site, error) { // Geocode geo, err := geocode.GeocodeRaw(ctx, user.Organization.model, address) if err != nil { @@ -124,9 +113,9 @@ func siteFromAddressRaw(ctx context.Context, txn bob.Tx, user User, address stri if err != nil { return nil, fmt.Errorf("ensure address: %w", err) } - return siteFromAddress(ctx, txn, user, a.ID) + return querypublic.SiteFromAddressIDForOrg(ctx, txn, int64(*a.ID), int64(user.Organization.ID)) } -func siteFromLocation(ctx context.Context, txn bob.Tx, user User, location types.Location) (*models.Site, error) { +func siteFromLocation(ctx context.Context, txn db.Ex, user User, location types.Location) (*model.Site, error) { // Reverse geocode at the location resp, err := geocode.ReverseGeocode(ctx, location) if err != nil { @@ -137,7 +126,7 @@ func siteFromLocation(ctx context.Context, txn bob.Tx, user User, location types if err != nil { return nil, fmt.Errorf("ensure address: %w", err) } - return siteFromAddress(ctx, txn, user, a.ID) + return querypublic.SiteFromAddressIDForOrg(ctx, txn, int64(*a.ID), int64(user.Organization.ID)) } func siteQuery() bob.BaseQuery[*dialect.SelectQuery] { return psql.Select( diff --git a/platform/types/address.go b/platform/types/address.go index e552f2ad..d6a02ec0 100644 --- a/platform/types/address.go +++ b/platform/types/address.go @@ -9,7 +9,7 @@ import ( "github.com/Gleipnir-Technology/bob/dialect/psql/sm" "github.com/Gleipnir-Technology/nidus-sync/db" - "github.com/Gleipnir-Technology/nidus-sync/db/models" + "github.com/Gleipnir-Technology/nidus-sync/db/gen/nidus-sync/public/model" //"github.com/rs/zerolog/log" "github.com/stephenafamo/scan" ) @@ -31,7 +31,7 @@ type Address struct { func (a Address) String() string { return fmt.Sprintf("%s %s, %s, %s, %s, %s", a.Number, a.Street, a.Locality, a.Region, a.PostalCode, a.Country) } -func AddressFromModel(m *models.Address) Address { +func AddressFromModel(m model.Address) Address { //log.Debug().Int32("id", m.ID).Float64("lat", m.LocationLatitude.GetOr(0.0)).Float64("lng", m.LocationLongitude.GetOr(0.0)).Msg("converting address") return Address{ Country: m.Country, @@ -39,12 +39,12 @@ func AddressFromModel(m *models.Address) Address { ID: &m.ID, Locality: m.Locality, Location: &Location{ - Latitude: m.LocationLatitude.GetOr(0.0), - Longitude: m.LocationLongitude.GetOr(0.0), + Latitude: *m.LocationLatitude, + Longitude: *m.LocationLongitude, }, Number: m.Number, PostalCode: m.PostalCode, - Raw: addressToRaw(*m), + Raw: addressToRaw(m), Region: m.Region, Street: m.Street, Unit: m.Unit, @@ -82,6 +82,6 @@ func AddressList(ctx context.Context, ids []int32) (map[int32]*Address, error) { func AddressToRaw(a Address) string { return fmt.Sprintf("%s %s, %s, %s", a.Number, a.Street, a.Locality, a.Region) } -func addressToRaw(m models.Address) string { +func addressToRaw(m model.Address) string { return fmt.Sprintf("%s %s, %s, %s", m.Number, m.Street, m.Locality, m.Region) } diff --git a/platform/types/location.go b/platform/types/location.go index e14a3ca0..61f00a8b 100644 --- a/platform/types/location.go +++ b/platform/types/location.go @@ -5,8 +5,10 @@ import ( "math" "github.com/Gleipnir-Technology/nidus-sync/db/models" + "github.com/Gleipnir-Technology/nidus-sync/geomutil" "github.com/Gleipnir-Technology/nidus-sync/h3utils" //"github.com/rs/zerolog/log" + "github.com/twpayne/go-geom" "github.com/uber/h3-go/v4" ) @@ -34,6 +36,9 @@ func (l Location) H3Cell() (*h3.Cell, error) { func (l Location) GeometryQuery() (string, error) { return fmt.Sprintf("ST_Point(%f, %f, 4326)", l.Longitude, l.Latitude), nil } +func (l Location) ToGeom() geom.T { + return geomutil.PointFromLngLat(l.Longitude, l.Latitude) +} func LocationFromFS(pl *models.FieldseekerPointlocation) Location { return Location{} } diff --git a/resource/communication.go b/resource/communication.go index 5aaf82ef..c50a5edb 100644 --- a/resource/communication.go +++ b/resource/communication.go @@ -3,9 +3,7 @@ package resource import ( "context" "net/http" - "slices" "strconv" - "time" "github.com/Gleipnir-Technology/nidus-sync/config" modelpublic "github.com/Gleipnir-Technology/nidus-sync/db/gen/nidus-sync/public/model" @@ -27,17 +25,20 @@ func Communication(r *router) *communicationR { } } +type communicationLog struct { + Created string `json:"string"` + ID string `json:"id"` + Type string `json:"type"` + User string `json:"user"` +} type communication struct { - Closed *time.Time `json:"closed"` - ClosedBy string `json:"closed_by"` - Created time.Time `json:"created"` - ID string `json:"id"` - Opened *time.Time `json:"opened"` - OpenedBy string `json:"opened_by"` - Response string `json:"response"` - Source string `json:"source"` - Type string `json:"type"` - URI string `json:"uri"` + ID string `json:"id"` + Log []communicationLog `json:"log"` + Response string `json:"response"` + Source string `json:"source"` + Status string `json:"status"` + Type string `json:"type"` + URI string `json:"uri"` } func toImageURLs(m map[string][]uuid.UUID, id string) []string { @@ -69,7 +70,7 @@ func (res *communicationR) List(ctx context.Context, r *http.Request, user platf if err != nil { return nil, nhttp.NewError("public reports from IDs: %w", err) } - public_report_id_to_report := make(map[int32]*modelpublicreport.Report, 0) + public_report_id_to_report := make(map[int32]modelpublicreport.Report, 0) for _, pr := range public_reports { public_report_id_to_report[pr.ID] = pr } @@ -79,22 +80,12 @@ func (res *communicationR) List(ctx context.Context, r *http.Request, user platf if !ok { return nil, nhttp.NewError("lookup report id %d failed", comm.SourceReportID) } - c, err := res.hydrateCommunication(*comm, public_report) + c, err := res.hydrateCommunication(comm, &public_report) if err != nil { return nil, err } result[i] = c } - _by_created := func(a, b communication) int { - if a.Created.Equal(b.Created) { - return 0 - } else if a.Created.Before(b.Created) { - return 1 - } else { - return -1 - } - } - slices.SortFunc(result, _by_created) return result, nil } @@ -135,14 +126,6 @@ func (res *communicationR) hydrateCommunication(comm modelpublic.Communication, } source_uri = "text" } - closed_by, err := userURI(res.router, comm.ClosedBy) - if err != nil { - return communication{}, nhttp.NewError("gen closed_by URI: %w", err) - } - opened_by, err := userURI(res.router, comm.OpenedBy) - if err != nil { - return communication{}, nhttp.NewError("gen opened_by URI: %w", err) - } response, err := responseURI(*res.router, comm) if err != nil { return communication{}, nhttp.NewError("gen response URI: %w", err) @@ -152,20 +135,16 @@ func (res *communicationR) hydrateCommunication(comm modelpublic.Communication, return communication{}, nhttp.NewError("gen comm uri: %w", err) } return communication{ - Closed: comm.Closed, - ClosedBy: closed_by, - Created: comm.Created, ID: strconv.Itoa(int(comm.ID)), - Opened: comm.Opened, - OpenedBy: opened_by, Response: response, Source: source_uri, + Status: comm.Status.String(), Type: type_, URI: uri, }, nil } -type markFunc = func(context.Context, platform.User, int64) error +type markFunc = func(context.Context, platform.User, int32) error func (res *communicationR) markCommunication(ctx context.Context, r *http.Request, user platform.User, status string, m markFunc) (communication, *nhttp.ErrorWithStatus) { vars := mux.Vars(r) @@ -177,12 +156,12 @@ func (res *communicationR) markCommunication(ctx context.Context, r *http.Reques if err != nil { return communication{}, nhttp.NewBadRequest("can't turn report ID into an int: %w", err) } - m(ctx, user, int64(comm_id)) + m(ctx, user, int32(comm_id)) result, err := platform.CommunicationFromID(ctx, user, int64(comm_id)) if result == nil { return communication{}, nhttp.NewUnauthorized("you are not authorized to modify communication %d", comm_id) } - var public_report *modelpublicreport.Report + var public_report modelpublicreport.Report if result.SourceReportID != nil { comm_ids := []int64{int64(*result.SourceReportID)} public_reports, err := platform.PublicReportsFromIDs(ctx, comm_ids) @@ -193,7 +172,7 @@ func (res *communicationR) markCommunication(ctx context.Context, r *http.Reques } log.Info().Int("communication", comm_id).Str("status", status).Msg("Marked communication") - return res.hydrateCommunication(*result, public_report) + return res.hydrateCommunication(*result, &public_report) } func responseURI(r router, comm modelpublic.Communication) (string, error) { if comm.ResponseEmailLogID != nil { diff --git a/resource/publicreport_compliance.go b/resource/publicreport_compliance.go index 90f5b22b..c6ad7fca 100644 --- a/resource/publicreport_compliance.go +++ b/resource/publicreport_compliance.go @@ -6,7 +6,10 @@ import ( "time" "github.com/Gleipnir-Technology/nidus-sync/db/enums" - "github.com/Gleipnir-Technology/nidus-sync/db/models" + modelpublicreport "github.com/Gleipnir-Technology/nidus-sync/db/gen/nidus-sync/publicreport/model" + tablepublicreport "github.com/Gleipnir-Technology/nidus-sync/db/gen/nidus-sync/publicreport/table" + querypublicreport "github.com/Gleipnir-Technology/nidus-sync/db/query/publicreport" + "github.com/aarondl/opt/omit" "github.com/aarondl/opt/omitnull" //"github.com/Gleipnir-Technology/nidus-sync/html" @@ -29,21 +32,21 @@ type complianceR struct { } type publicReportComplianceForm struct { - AccessInstructions omit.Val[string] `schema:"access_instructions" json:"access_instructions"` - Address omit.Val[types.Address] `schema:"address" json:"address"` - AvailabilityNotes omit.Val[string] `schema:"availability_notes" json:"availability_notes"` - ClientID uuid.UUID `schema:"client_id" json:"client_id"` - Comments omit.Val[string] `schema:"comments" json:"comments"` - District omit.Val[string] `schema:"district" json:"district"` - GateCode omit.Val[string] `schema:"gate_code" json:"gate_code"` - HasDog omitnull.Val[bool] `schema:"has_dog" json:"has_dog"` - Location omit.Val[types.Location] `schema:"location" json:"location"` - MailerID omit.Val[string] `schema:"mailer_id" json:"mailer_id"` - PermissionType omit.Val[enums.PublicreportPermissionaccesstype] `schema:"permission_type" json:"permission_type"` - Reporter omit.Val[types.Contact] `schema:"reporter" json:"reporter"` - ReportPhoneCanSMS omitnull.Val[bool] `schema:"report_phone_can_text" json:"report_phone_can_text"` - Submitted omitnull.Val[time.Time] `schema:"submitted" json:"submitted"` - WantsScheduled omitnull.Val[bool] `schema:"wants_scheduled" json:"wants_scheduled"` + AccessInstructions omit.Val[string] `schema:"access_instructions" json:"access_instructions"` + Address omit.Val[types.Address] `schema:"address" json:"address"` + AvailabilityNotes omit.Val[string] `schema:"availability_notes" json:"availability_notes"` + ClientID uuid.UUID `schema:"client_id" json:"client_id"` + Comments omit.Val[string] `schema:"comments" json:"comments"` + District omit.Val[string] `schema:"district" json:"district"` + GateCode omit.Val[string] `schema:"gate_code" json:"gate_code"` + HasDog omitnull.Val[bool] `schema:"has_dog" json:"has_dog"` + Location omit.Val[types.Location] `schema:"location" json:"location"` + MailerID omit.Val[string] `schema:"mailer_id" json:"mailer_id"` + PermissionType omit.Val[enums.PublicreportPermissionaccess] `schema:"permission_type" json:"permission_type"` + Reporter omit.Val[types.Contact] `schema:"reporter" json:"reporter"` + ReportPhoneCanSMS omitnull.Val[bool] `schema:"report_phone_can_text" json:"report_phone_can_text"` + Submitted omitnull.Val[time.Time] `schema:"submitted" json:"submitted"` + WantsScheduled omitnull.Val[bool] `schema:"wants_scheduled" json:"wants_scheduled"` } func (res *complianceR) ByID(ctx context.Context, r *http.Request, u platform.User, query QueryParams) (*types.PublicReportCompliance, *nhttp.ErrorWithStatus) { @@ -61,36 +64,36 @@ func (res *complianceR) Create(ctx context.Context, r *http.Request, n publicRep if err != nil { return nil, nhttp.NewError("Failed to ensure client: %w", err) } - setter_report := models.PublicreportReportSetter{ + setter_report := modelpublicreport.Report{ //AddressID: omitnull.From(...), - AddressGid: omit.From(""), - AddressRaw: omit.From(""), - ClientUUID: omitnull.From(n.ClientID), - Created: omit.From(time.Now()), + AddressGid: "", + AddressRaw: "", + ClientUUID: &n.ClientID, + Created: time.Now(), //H3cell: omitnull.From(latlng.Cell.String()), - LatlngAccuracyType: omit.From(enums.PublicreportAccuracytypeBrowser), - LatlngAccuracyValue: omit.From(float32(0.0)), + LatlngAccuracyType: modelpublicreport.Accuracytype_Browser, + LatlngAccuracyValue: float32(0.0), //Location: omitnull.From(fmt.Sprintf("ST_GeometryFromText(Point(%s %s))", longitude, latitude)), - Location: omitnull.FromPtr[string](nil), - MapZoom: omit.From(float32(0.0)), - //OrganizationID: omit.From[int32](), - //PublicID: omit.From(), - ReporterEmail: omit.From(""), - ReporterName: omit.From(""), - ReporterPhone: omit.From(""), - ReporterPhoneCanSMS: omit.From(true), - ReportType: omit.From(enums.PublicreportReporttypeCompliance), - Status: omit.From(enums.PublicreportReportstatustypeReported), + Location: nil, + MapZoom: float32(0.0), + //OrganizationID: , + //PublicID: + ReporterEmail: "", + ReporterName: "", + ReporterPhone: "", + ReporterPhoneCanSms: true, + ReportType: modelpublicreport.Reporttype_Compliance, + Status: modelpublicreport.Reportstatustype_Reported, } - setter_compliance := models.PublicreportComplianceSetter{ - AccessInstructions: omit.From(""), - AvailabilityNotes: omit.From(""), - Comments: omit.From(""), - GateCode: omit.From(""), - HasDog: omitnull.FromPtr[bool](nil), - PermissionType: omit.From(enums.PublicreportPermissionaccesstypeUnselected), + setter_compliance := modelpublicreport.Compliance{ + AccessInstructions: "", + AvailabilityNotes: "", + Comments: "", + GateCode: "", + HasDog: nil, + PermissionType: modelpublicreport.Permissionaccess_Unselected, //ReportID omit.Val[int32] - WantsScheduled: omitnull.FromPtr[bool](nil), + WantsScheduled: nil, } var org_id int32 if n.District.IsValue() { @@ -105,11 +108,11 @@ func (res *complianceR) Create(ctx context.Context, r *http.Request, n publicRep if err != nil { return nil, nhttp.NewError("generate public ID: %w", err) } - setter_report.PublicID = omit.From(public_id) + setter_report.PublicID = public_id } if n.MailerID.IsValue() { public_id := n.MailerID.MustGet() - setter_report.PublicID = omit.From(public_id) + setter_report.PublicID = public_id // If it already exists, just return it report, err := platform.PublicReportByIDCompliance(ctx, public_id, true) @@ -128,8 +131,8 @@ func (res *complianceR) Create(ctx context.Context, r *http.Request, n publicRep if err != nil { return nil, nhttp.NewError("get address gid: %w", err) } - setter_report.AddressID = omitnull.FromPtr(address.ID) - setter_report.AddressGid = omit.From(address.GID) + setter_report.AddressID = address.ID + setter_report.AddressGid = address.GID } report, err := platform.PublicReportComplianceCreate(ctx, setter_report, setter_compliance, org_id) if err != nil { @@ -143,34 +146,47 @@ func (res *complianceR) Create(ctx context.Context, r *http.Request, n publicRep return res.complianceHydrate(result, true) } func (res *complianceR) Update(ctx context.Context, r *http.Request, prf publicReportComplianceForm) (*types.PublicReportCompliance, *nhttp.ErrorWithStatus) { + var err error vars := mux.Vars(r) public_id := vars["id"] if public_id == "" { return nil, nhttp.NewBadRequest("You must provide an ID") } - report_setter := models.PublicreportReportSetter{} - compliance_setter := models.PublicreportComplianceSetter{} + report_updater := querypublicreport.ReportUpdater{} + //report_setter := models.PublicreportReportSetter{} + compliance_updater := querypublicreport.ComplianceUpdater{} + //compliance_setter := models.PublicreportComplianceSetter{} var location *types.Location if prf.Location.IsValue() { l := prf.Location.MustGet() location = &l if location.Accuracy != nil { - report_setter.LatlngAccuracyValue = omit.From(*location.Accuracy) + //report_setter.LatlngAccuracyValue = omit.From(*location.Accuracy) + report_updater.Model.LatlngAccuracyValue = *location.Accuracy + report_updater.Set(tablepublicreport.Report.LatlngAccuracyValue) } } if prf.Reporter.IsValue() { reporter := prf.Reporter.MustGet() if reporter.Email != nil { - report_setter.ReporterEmail = omit.From(*reporter.Email) + //report_setter.ReporterEmail = omit.From(*reporter.Email) + report_updater.Model.ReporterEmail = *reporter.Email + report_updater.Set(tablepublicreport.Report.ReporterEmail) } if reporter.Name != nil { - report_setter.ReporterName = omit.From(*reporter.Name) + //report_setter.ReporterName = omit.From(*reporter.Name) + report_updater.Model.ReporterName = *reporter.Name + report_updater.Set(tablepublicreport.Report.ReporterName) } if reporter.Phone != nil { - report_setter.ReporterPhone = omit.From(*reporter.Phone) + //report_setter.ReporterPhone = omit.From(*reporter.Phone) + report_updater.Model.ReporterPhone = *reporter.Phone + report_updater.Set(tablepublicreport.Report.ReporterPhone) } if reporter.CanSMS != nil { - report_setter.ReporterPhoneCanSMS = omit.FromPtr(reporter.CanSMS) + //report_setter.ReporterPhoneCanSMS = omit.FromPtr(reporter.CanSMS) + report_updater.Model.ReporterPhoneCanSms = *reporter.CanSMS + report_updater.Set(tablepublicreport.Report.ReporterPhoneCanSms) } } var address *types.Address @@ -179,36 +195,61 @@ func (res *complianceR) Update(ctx context.Context, r *http.Request, prf publicR address = &a } if prf.AccessInstructions.IsValue() { - compliance_setter.AccessInstructions = prf.AccessInstructions + //compliance_setter.AccessInstructions = prf.AccessInstructions + compliance_updater.Model.AccessInstructions = prf.AccessInstructions.MustGet() + compliance_updater.Set(tablepublicreport.Compliance.AccessInstructions) } if prf.AvailabilityNotes.IsValue() { - compliance_setter.AvailabilityNotes = prf.AvailabilityNotes + //compliance_setter.AvailabilityNotes = prf.AvailabilityNotes + compliance_updater.Model.AvailabilityNotes = prf.AvailabilityNotes.MustGet() + compliance_updater.Set(tablepublicreport.Compliance.AvailabilityNotes) } if prf.Comments.IsValue() { - compliance_setter.Comments = prf.Comments + //compliance_setter.Comments = prf.Comments + compliance_updater.Model.Comments = prf.Comments.MustGet() + compliance_updater.Set(tablepublicreport.Compliance.Comments) } if prf.GateCode.IsValue() { - compliance_setter.GateCode = prf.GateCode + //compliance_setter.GateCode = prf.GateCode + compliance_updater.Model.GateCode = prf.GateCode.MustGet() + compliance_updater.Set(tablepublicreport.Compliance.GateCode) } if prf.HasDog.IsValue() { - compliance_setter.HasDog = prf.HasDog + //compliance_setter.HasDog = prf.HasDog + has_dog := prf.HasDog.MustGet() + compliance_updater.Model.HasDog = &has_dog + compliance_updater.Set(tablepublicreport.Compliance.HasDog) } if prf.PermissionType.IsValue() { - compliance_setter.PermissionType = prf.PermissionType + //compliance_setter.PermissionType = prf.PermissionType + var perm_type modelpublicreport.Permissionaccess + pt := prf.PermissionType.MustGet() + err = perm_type.Scan(pt) + if err != nil { + return nil, nhttp.NewBadRequest("permission type %s can't be scanned: %w", pt, err) + } + compliance_updater.Model.PermissionType = perm_type + compliance_updater.Set(tablepublicreport.Compliance.PermissionType) } if prf.WantsScheduled.IsValue() { - compliance_setter.WantsScheduled = prf.WantsScheduled + //compliance_setter.WantsScheduled = prf.WantsScheduled + wants_scheduled := prf.WantsScheduled.MustGet() + compliance_updater.Model.WantsScheduled = &wants_scheduled + compliance_updater.Set(tablepublicreport.Compliance.WantsScheduled) } if prf.Submitted.IsValue() { log.Debug().Str("submitted", prf.Submitted.MustGet().String()).Msg("got submitted") - compliance_setter.Submitted = omitnull.From(time.Now()) + //compliance_setter.Submitted = omitnull.From(time.Now()) + now := time.Now() + compliance_updater.Model.Submitted = &now + compliance_updater.Set(tablepublicreport.Compliance.Submitted) } - report, err := platform.PublicReportUpdateCompliance(ctx, public_id, &report_setter, &compliance_setter, address, location) + err = platform.PublicReportUpdateCompliance(ctx, public_id, report_updater, compliance_updater, address, location) if err != nil { return nil, nhttp.NewError("platform update report compliance: %w", err) } // Return a fully-fleshed-out report object, even though it's a bit more expensive - report, err = platform.PublicReportByIDCompliance(ctx, public_id, true) + report, err := platform.PublicReportByIDCompliance(ctx, public_id, true) if err != nil { return nil, nhttp.NewError("get report after update: %w", err) } diff --git a/resource/publicreport_nuisance.go b/resource/publicreport_nuisance.go index 62965f1d..12f808ab 100644 --- a/resource/publicreport_nuisance.go +++ b/resource/publicreport_nuisance.go @@ -6,14 +6,13 @@ import ( "slices" "time" - "github.com/Gleipnir-Technology/nidus-sync/db/enums" - "github.com/Gleipnir-Technology/nidus-sync/db/models" + modelpublicreport "github.com/Gleipnir-Technology/nidus-sync/db/gen/nidus-sync/publicreport/model" + //tablepublicreport "github.com/Gleipnir-Technology/nidus-sync/db/gen/nidus-sync/publicreport/table" + //querypublicreport "github.com/Gleipnir-Technology/nidus-sync/db/query/publicreport" "github.com/Gleipnir-Technology/nidus-sync/html" nhttp "github.com/Gleipnir-Technology/nidus-sync/http" "github.com/Gleipnir-Technology/nidus-sync/platform" "github.com/Gleipnir-Technology/nidus-sync/platform/types" - "github.com/aarondl/opt/omit" - "github.com/aarondl/opt/omitnull" "github.com/google/uuid" "github.com/gorilla/mux" "github.com/rs/zerolog/log" @@ -63,7 +62,7 @@ func (res *nuisanceR) Create(ctx context.Context, r *http.Request, n nuisanceFor if err != nil { return nil, nhttp.NewError("Failed to ensure client: %w", err) } - duration := enums.PublicreportNuisancedurationtypeNone + duration := modelpublicreport.Nuisancedurationtype_None is_location_frontyard := slices.Contains(n.SourceLocations, "frontyard") is_location_backyard := slices.Contains(n.SourceLocations, "backyard") is_location_garden := slices.Contains(n.SourceLocations, "garden") @@ -84,44 +83,44 @@ func (res *nuisanceR) Create(ctx context.Context, r *http.Request, n nuisanceFor if n.Location.Accuracy != nil { accuracy = *n.Location.Accuracy } - setter_report := models.PublicreportReportSetter{ - //AddressID: omitnull.From(latlng.Cell.String()), - AddressGid: omit.From(n.Address.GID), - AddressRaw: omit.From(n.Address.Raw), - ClientUUID: omitnull.From(n.ClientID), - Created: omit.From(time.Now()), + setter_report := modelpublicreport.Report{ + //AddressID: omitnull.From(...), + AddressGid: "", + AddressRaw: "", + ClientUUID: &n.ClientID, + Created: time.Now(), //H3cell: omitnull.From(latlng.Cell.String()), - LatlngAccuracyType: omit.From(enums.PublicreportAccuracytypeBrowser), - LatlngAccuracyValue: omit.From(accuracy), + LatlngAccuracyType: modelpublicreport.Accuracytype_Browser, + LatlngAccuracyValue: accuracy, //Location: omitnull.From(fmt.Sprintf("ST_GeometryFromText(Point(%s %s))", longitude, latitude)), - Location: omitnull.FromPtr[string](nil), - MapZoom: omit.From(float32(0.0)), - //OrganizationID: omitnull.FromPtr(organization_id), - //PublicID: omit.From(public_id), - ReporterEmail: omit.From(""), - ReporterName: omit.From(""), - ReporterPhone: omit.From(""), - ReporterPhoneCanSMS: omit.From(true), - ReportType: omit.From(enums.PublicreportReporttypeNuisance), - Status: omit.From(enums.PublicreportReportstatustypeReported), + Location: nil, + MapZoom: float32(0.0), + //OrganizationID: , + //PublicID: + ReporterEmail: "", + ReporterName: "", + ReporterPhone: "", + ReporterPhoneCanSms: true, + ReportType: modelpublicreport.Reporttype_Nuisance, + Status: modelpublicreport.Reportstatustype_Reported, } - setter_nuisance := models.PublicreportNuisanceSetter{ - AdditionalInfo: omit.From(n.AdditionalInfo), - Duration: omit.From(duration), - IsLocationBackyard: omit.From(is_location_backyard), - IsLocationFrontyard: omit.From(is_location_frontyard), - IsLocationGarden: omit.From(is_location_garden), - IsLocationOther: omit.From(is_location_other), - IsLocationPool: omit.From(is_location_pool), + setter_nuisance := modelpublicreport.Nuisance{ + AdditionalInfo: n.AdditionalInfo, + Duration: duration, + IsLocationBackyard: is_location_backyard, + IsLocationFrontyard: is_location_frontyard, + IsLocationGarden: is_location_garden, + IsLocationOther: is_location_other, + IsLocationPool: is_location_pool, //ReportID omit.Val[int32] - SourceContainer: omit.From(n.SourceContainer), - SourceDescription: omit.From(n.SourceDescription), - SourceGutter: omit.From(n.SourceGutters), - SourceStagnant: omit.From(n.SourceStagnant), - TodDay: omit.From(n.TODDay), - TodEarly: omit.From(n.TODEarly), - TodEvening: omit.From(n.TODEvening), - TodNight: omit.From(n.TODNight), + SourceContainer: n.SourceContainer, + SourceDescription: n.SourceDescription, + SourceGutter: n.SourceGutters, + SourceStagnant: n.SourceStagnant, + TodDay: n.TODDay, + TodEarly: n.TODEarly, + TodEvening: n.TODEvening, + TodNight: n.TODNight, } report, err := platform.PublicReportNuisanceCreate(ctx, setter_report, setter_nuisance, n.Location, n.Address, uploads) if err != nil { diff --git a/resource/publicreport_water.go b/resource/publicreport_water.go index 58733729..8bd2742b 100644 --- a/resource/publicreport_water.go +++ b/resource/publicreport_water.go @@ -5,14 +5,14 @@ import ( "net/http" "time" - "github.com/Gleipnir-Technology/nidus-sync/db/enums" - "github.com/Gleipnir-Technology/nidus-sync/db/models" + modelpublicreport "github.com/Gleipnir-Technology/nidus-sync/db/gen/nidus-sync/publicreport/model" + //tablepublicreport "github.com/Gleipnir-Technology/nidus-sync/db/gen/nidus-sync/publicreport/table" + //querypublicreport "github.com/Gleipnir-Technology/nidus-sync/db/query/publicreport" "github.com/Gleipnir-Technology/nidus-sync/html" nhttp "github.com/Gleipnir-Technology/nidus-sync/http" "github.com/Gleipnir-Technology/nidus-sync/platform" "github.com/Gleipnir-Technology/nidus-sync/platform/types" "github.com/aarondl/opt/omit" - "github.com/aarondl/opt/omitnull" "github.com/google/uuid" "github.com/gorilla/mux" "github.com/rs/zerolog/log" @@ -43,7 +43,7 @@ type waterForm struct { AddressGID string `schema:"address-gid"` ClientID uuid.UUID `schema:"client_id" json:"client_id"` Comments string `schema:"comments"` - Duration omit.Val[enums.PublicreportNuisancedurationtype] `schema:"duration"` + Duration omit.Val[modelpublicreport.Nuisancedurationtype] `schema:"duration"` HasAdult bool `schema:"has-adult"` HasBackyardPermission bool `schema:"backyard-permission"` HasLarvae bool `schema:"has-larvae"` @@ -80,44 +80,45 @@ func (res *waterR) Create(ctx context.Context, r *http.Request, w waterForm) (*w if w.Location.Accuracy != nil { accuracy = *w.Location.Accuracy } - setter_report := models.PublicreportReportSetter{ - AddressGid: omit.From(w.Address.GID), - AddressRaw: omit.From(w.Address.Raw), - ClientUUID: omitnull.From(w.ClientID), - Created: omit.From(time.Now()), - //H3cell: omitnull.From(geospatial.Cell.String()), - LatlngAccuracyType: omit.From(enums.PublicreportAccuracytypeBrowser), - LatlngAccuracyValue: omit.From(accuracy), - //Location: add later - Location: omitnull.FromPtr[string](nil), - MapZoom: omit.From(float32(0.0)), - //OrganizationID: omitnull.FromPtr(organization_id), - //PublicID: omit.From(public_id), - ReporterEmail: omit.From(""), - ReporterName: omit.From(""), - ReporterPhone: omit.From(""), - ReporterPhoneCanSMS: omit.From(true), - ReportType: omit.From(enums.PublicreportReporttypeWater), - Status: omit.From(enums.PublicreportReportstatustypeReported), + setter_report := modelpublicreport.Report{ + //AddressID: omitnull.From(...), + AddressGid: w.Address.GID, + AddressRaw: w.Address.Raw, + ClientUUID: &w.ClientID, + Created: time.Now(), + //H3cell: omitnull.From(latlng.Cell.String()), + LatlngAccuracyType: modelpublicreport.Accuracytype_Browser, + LatlngAccuracyValue: accuracy, + //Location: omitnull.From(fmt.Sprintf("ST_GeometryFromText(Point(%s %s))", longitude, latitude)), + Location: nil, + MapZoom: float32(0.0), + //OrganizationID: , + //PublicID: + ReporterEmail: "", + ReporterName: "", + ReporterPhone: "", + ReporterPhoneCanSms: true, + ReportType: modelpublicreport.Reporttype_Water, + Status: modelpublicreport.Reportstatustype_Reported, } - setter_water := models.PublicreportWaterSetter{ - AccessComments: omit.From(w.AccessComments), - AccessDog: omit.From(w.AccessDog), - AccessFence: omit.From(w.AccessFence), - AccessGate: omit.From(w.AccessGate), - AccessLocked: omit.From(w.AccessLocked), - AccessOther: omit.From(w.AccessOther), - Comments: omit.From(w.Comments), - Duration: w.Duration, - HasAdult: omit.From(w.HasAdult), - HasBackyardPermission: omit.From(w.HasBackyardPermission), - HasLarvae: omit.From(w.HasLarvae), - HasPupae: omit.From(w.HasPupae), - IsReporterConfidential: omit.From(w.IsReporterConfidential), - IsReporterOwner: omit.From(w.IsReporter_owner), - OwnerEmail: omit.From(w.OwnerEmail), - OwnerName: omit.From(w.OwnerName), - OwnerPhone: omit.From(w.OwnerPhone), + setter_water := modelpublicreport.Water{ + AccessComments: w.AccessComments, + AccessDog: w.AccessDog, + AccessFence: w.AccessFence, + AccessGate: w.AccessGate, + AccessLocked: w.AccessLocked, + AccessOther: w.AccessOther, + Comments: w.Comments, + Duration: w.Duration.GetOr(modelpublicreport.Nuisancedurationtype_None), + HasAdult: w.HasAdult, + HasBackyardPermission: w.HasBackyardPermission, + HasLarvae: w.HasLarvae, + HasPupae: w.HasPupae, + IsReporterConfidential: w.IsReporterConfidential, + IsReporterOwner: w.IsReporter_owner, + OwnerEmail: w.OwnerEmail, + OwnerName: w.OwnerName, + OwnerPhone: w.OwnerPhone, //ReportID omit.Val[int32] } report, err := platform.PublicReportWaterCreate(ctx, setter_report, setter_water, w.Location, w.Address, uploads)