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...
This commit is contained in:
Eli Ribble 2026-05-07 10:39:17 +00:00
parent a95e44cf42
commit fcd95f1a25
No known key found for this signature in database
65 changed files with 3129 additions and 3457 deletions

View file

@ -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,
}

53
cmd/test-jet/main.go Normal file
View file

@ -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)
*/
}

View file

@ -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)
}
func ExecuteOneTx[T any](ctx context.Context, txn Tx, stmt postgres.Statement) (*T, error) {
return *collected, nil
}
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 *collected, nil
}
return &results[0], err
}
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)
config, err := pgxpool.ParseConfig(uri)
if err != nil {
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}
err = e
})
if err != nil {
return fmt.Errorf("unable to create connection pool: %w", err)
}
var current string
query := `SELECT current_database()`

View file

@ -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
}

View file

@ -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
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,15 +210,9 @@ 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
@ -390,7 +220,7 @@ type communicationForeignKeys struct {
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,
}
}

View file

@ -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{}
}

View file

@ -62,7 +62,7 @@ var PublicreportCompliances = Table[
},
PermissionType: column{
Name: "permission_type",
DBType: "publicreport.permissionaccesstype",
DBType: "publicreport.permissionaccess",
Default: "",
Comment: "",
Nullable: false,

View file

@ -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

View file

@ -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 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 {
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(types.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 {
customSchema := template.DefaultSchema(schema)
customSchema = customSchema.UseModel(template.DefaultModel().UseTable(customTableModel))
customSchema = customSchema.UseSQLBuilder(template.DefaultSQLBuilder().UseTable(customTableSQLBuilder))
return customSchema
})
}

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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);

View file

@ -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](),

View file

@ -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),

File diff suppressed because it is too large Load diff

View file

@ -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
}

View file

@ -31,7 +31,7 @@ type PublicreportCompliance struct {
Comments string `db:"comments" `
GateCode string `db:"gate_code" `
HasDog null.Val[bool] `db:"has_dog" `
PermissionType enums.PublicreportPermissionaccesstype `db:"permission_type" `
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" `
@ -106,7 +106,7 @@ type PublicreportComplianceSetter struct {
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" `
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" `
@ -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),

File diff suppressed because it is too large Load diff

View file

@ -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)

View file

@ -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,

View file

@ -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)

View file

@ -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).

View file

@ -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)

View file

@ -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"),
}

View file

@ -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))))

View file

@ -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)
}

19
db/query/public/signal.go Normal file
View file

@ -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)
}

38
db/query/public/site.go Normal file
View file

@ -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)
}

View file

@ -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)
}

View file

@ -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)
}

View file

@ -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)
}

View file

@ -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)
}

View file

@ -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).
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.ExecuteOne[model.Communication](ctx, statement)
return db.ExecuteOneTx[model.Report](ctx, txn, statement)
}
*/
func PublicReportsFromIDs(ctx context.Context, report_ids []int64) ([]*model.Report, error) {
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
}

View file

@ -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)
}

View file

@ -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)
}

View file

@ -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)
}

83
db/tx.go Normal file
View file

@ -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
}

View file

@ -1,8 +0,0 @@
package types
type Box2D struct {
XMax float64
YMax float64
XMin float64
YMin float64
}

64
db/updater.go Normal file
View file

@ -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...)
},
}
}

9
geomutil/geomutil.go Normal file
View file

@ -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})
}

9
go.mod
View file

@ -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

18
go.sum
View file

@ -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=

View file

@ -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
}

100
platform/address/address.go Normal file
View file

@ -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
}

View file

@ -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,
},
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)

View file

@ -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)

View file

@ -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
}

View file

@ -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)
}

View file

@ -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)
}

View file

@ -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,

View file

@ -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)
}

View file

@ -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)
}

View file

@ -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
}

View file

@ -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)
}

View file

@ -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)
err = report_updates.Execute(ctx, txn, int64(report.ID))
if err != nil {
return nil, fmt.Errorf("update report: %w", err)
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)
err = compliance_updates.Execute(ctx, txn, int64(compliance.ReportID))
if err != nil {
return nil, fmt.Errorf("update compliance: %w", err)
}
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)
}

View file

@ -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

View file

@ -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)
}

View file

@ -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(

View file

@ -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)
}

View file

@ -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{}
}

View file

@ -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,15 +25,18 @@ func Communication(r *router) *communicationR {
}
}
type communication struct {
Closed *time.Time `json:"closed"`
ClosedBy string `json:"closed_by"`
Created time.Time `json:"created"`
type communicationLog struct {
Created string `json:"string"`
ID string `json:"id"`
Opened *time.Time `json:"opened"`
OpenedBy string `json:"opened_by"`
Type string `json:"type"`
User string `json:"user"`
}
type communication struct {
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"`
}
@ -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 {

View file

@ -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"
@ -39,7 +42,7 @@ type publicReportComplianceForm struct {
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"`
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"`
@ -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)
}

View file

@ -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 {

View file

@ -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)