Add trap count data to source page

It's...way too many rows, now that I have the actual data. It needs to
be reworked.
This commit is contained in:
Eli Ribble 2025-11-20 20:59:28 +00:00
parent 26ee3efcc8
commit e7ece52c8c
No known key found for this signature in database
32 changed files with 1622 additions and 298 deletions

View file

@ -10,6 +10,7 @@ import (
enums "github.com/Gleipnir-Technology/nidus-sync/enums"
"github.com/jaswdr/faker/v2"
"github.com/shopspring/decimal"
"github.com/stephenafamo/bob"
pg_query "github.com/wasilibs/go-pgquery"
)
@ -28,6 +29,37 @@ func formatQuery(s string) (string, error) {
var defaultFaker = faker.New()
func random_decimal_Decimal(f *faker.Faker, limits ...string) decimal.Decimal {
if f == nil {
f = &defaultFaker
}
var precision int64 = 7
var scale int64 = 3
if len(limits) > 0 {
precision, _ = strconv.ParseInt(limits[0], 10, 32)
}
if len(limits) > 1 {
scale, _ = strconv.ParseInt(limits[1], 10, 32)
}
baseVal := f.Float32(10, -1, 1)
for baseVal == -1 || baseVal == 0 || baseVal == 1 {
baseVal = f.Float32(10, -1, 1)
}
precisionDecimal, _ := decimal.NewFromInt(10).PowInt32(int32(precision))
val := decimal.
NewFromFloat32(baseVal).
Mul(precisionDecimal).
Shift(int32(-1 * scale)).
RoundDown(int32(scale))
return val
}
func random_enums_Arcgislicensetype(f *faker.Faker, limits ...string) enums.Arcgislicensetype {
if f == nil {
f = &defaultFaker
@ -56,6 +88,14 @@ func random_int32(f *faker.Faker, limits ...string) int32 {
return f.Int32()
}
func random_int64(f *faker.Faker, limits ...string) int64 {
if f == nil {
f = &defaultFaker
}
return f.Int64()
}
func random_string(f *faker.Faker, limits ...string) string {
if f == nil {
f = &defaultFaker

View file

@ -0,0 +1,114 @@
// Code generated by BobGen psql v0.41.1. DO NOT EDIT.
// This file is meant to be re-generated in place and/or deleted at any time.
package sql
import (
"context"
_ "embed"
"io"
"iter"
"github.com/aarondl/opt/null"
"github.com/shopspring/decimal"
"github.com/stephenafamo/bob"
"github.com/stephenafamo/bob/dialect/psql"
"github.com/stephenafamo/bob/dialect/psql/dialect"
"github.com/stephenafamo/bob/expr"
"github.com/stephenafamo/bob/orm"
"github.com/stephenafamo/scan"
)
//go:embed trapcount_by_location_id.bob.sql
var formattedQueries_trapcount_by_location_id string
var trapCountByLocationIDSQL = formattedQueries_trapcount_by_location_id[159:580]
type TrapCountByLocationIDQuery = orm.ModQuery[*dialect.SelectQuery, trapCountByLocationID, TrapCountByLocationIDRow, []TrapCountByLocationIDRow, trapCountByLocationIDTransformer]
func TrapCountByLocationID(OrganizationID int32, LocID []string) *TrapCountByLocationIDQuery {
var expressionTypArgs trapCountByLocationID
expressionTypArgs.OrganizationID = psql.Arg(OrganizationID)
expressionTypArgs.LocID = expr.ToArgs(LocID...)
return &TrapCountByLocationIDQuery{
Query: orm.Query[trapCountByLocationID, TrapCountByLocationIDRow, []TrapCountByLocationIDRow, trapCountByLocationIDTransformer]{
ExecQuery: orm.ExecQuery[trapCountByLocationID]{
BaseQuery: bob.BaseQuery[trapCountByLocationID]{
Expression: expressionTypArgs,
Dialect: dialect.Dialect,
QueryType: bob.QueryTypeSelect,
},
},
Scanner: func(context.Context, []string) (func(*scan.Row) (any, error), func(any) (TrapCountByLocationIDRow, error)) {
return func(row *scan.Row) (any, error) {
var t TrapCountByLocationIDRow
row.ScheduleScanByIndex(0, &t.TrapdataGlobalid)
row.ScheduleScanByIndex(1, &t.TrapdataEnddate)
row.ScheduleScanByIndex(2, &t.TotalFemales)
row.ScheduleScanByIndex(3, &t.TotalMales)
row.ScheduleScanByIndex(4, &t.Total)
return &t, nil
}, func(v any) (TrapCountByLocationIDRow, error) {
return *(v.(*TrapCountByLocationIDRow)), nil
}
},
},
Mod: bob.ModFunc[*dialect.SelectQuery](func(q *dialect.SelectQuery) {
q.AppendSelect(expressionTypArgs.subExpr(12, 223))
q.SetTable(expressionTypArgs.subExpr(234, 318))
q.AppendWhere(expressionTypArgs.subExpr(330, 379))
q.AppendGroup(expressionTypArgs.subExpr(394, 421))
}),
}
}
type TrapCountByLocationIDRow = struct {
TrapdataGlobalid string `db:"trapdata_globalid"`
TrapdataEnddate null.Val[int64] `db:"trapdata_enddate"`
TotalFemales decimal.Decimal `db:"total_females"`
TotalMales int64 `db:"total_males"`
Total decimal.Decimal `db:"total"`
}
type trapCountByLocationIDTransformer = bob.SliceTransformer[TrapCountByLocationIDRow, []TrapCountByLocationIDRow]
type trapCountByLocationID struct {
OrganizationID bob.Expression
LocID bob.Expression
}
func (o trapCountByLocationID) args() iter.Seq[orm.ArgWithPosition] {
return func(yield func(arg orm.ArgWithPosition) bool) {
if !yield(orm.ArgWithPosition{
Name: "organizationID",
Start: 351,
Stop: 353,
Expression: o.OrganizationID,
}) {
return
}
if !yield(orm.ArgWithPosition{
Name: "locID",
Start: 376,
Stop: 378,
Expression: o.LocID,
}) {
return
}
}
}
func (o trapCountByLocationID) raw(from, to int) string {
return trapCountByLocationIDSQL[from:to]
}
func (o trapCountByLocationID) subExpr(from, to int) bob.Expression {
return orm.ArgsToExpression(trapCountByLocationIDSQL, from, to, o.args())
}
func (o trapCountByLocationID) WriteSQL(ctx context.Context, w io.Writer, d bob.Dialect, start int) ([]any, error) {
return o.subExpr(0, len(trapCountByLocationIDSQL)).WriteSQL(ctx, w, d, start)
}

View file

@ -0,0 +1,19 @@
-- Code generated by BobGen psql v0.41.1. DO NOT EDIT.
-- This file is meant to be re-generated in place and/or deleted at any time.
-- TrapCountByLocationID
SELECT
td.globalid AS trapdata_globalid,
td.enddatetime AS trapdata_enddate,
COALESCE(SUM(sa.females), 0) AS total_females,
COALESCE(SUM(sa.males), 0) AS total_males,
COALESCE(SUM(sa.total), 0) AS total
FROM
fs_trapdata td
LEFT JOIN
fs_speciesabundance sa ON td.globalid = sa.trapdata_id
WHERE
td.organization_id = $1
AND td.loc_id IN ($2)
GROUP BY
td.globalid, td.enddatetime;

View file

@ -0,0 +1,111 @@
// Code generated by BobGen psql v0.41.1. DO NOT EDIT.
// This file is meant to be re-generated in place and/or deleted at any time.
package sql
import (
"context"
"fmt"
"strings"
"testing"
"github.com/google/go-cmp/cmp"
"github.com/stephenafamo/bob"
"github.com/stephenafamo/bob/dialect/psql"
testutils "github.com/stephenafamo/bob/test/utils"
)
func TestTrapCountByLocationID(t *testing.T) {
t.Run("Base", func(t *testing.T) {
var sb strings.Builder
query := TrapCountByLocationID(random_int32(nil), []string{random_string(nil)})
if _, err := query.WriteQuery(t.Context(), &sb, 1); err != nil {
t.Fatal(err)
}
if diff := cmp.Diff(trapCountByLocationIDSQL, sb.String()); diff != "" {
t.Fatalf("unexpected result (-got +want):\n%s", diff)
}
})
t.Run("Mod", func(t *testing.T) {
var sb strings.Builder
query := TrapCountByLocationID(random_int32(nil), []string{random_string(nil)})
if _, err := psql.Select(query).WriteQuery(t.Context(), &sb, 1); err != nil {
t.Fatal(err)
}
queryDiff, err := testutils.QueryDiff(trapCountByLocationIDSQL, sb.String(), formatQuery)
if err != nil {
t.Fatal(err)
}
if queryDiff != "" {
fmt.Println(sb.String())
t.Fatalf("unexpected result (-got +want):\n%s", queryDiff)
}
})
t.Run("Scanning", func(t *testing.T) {
if testDB == nil {
t.Skip("skipping test, no DSN provided")
}
ctxTx, cancel := context.WithCancel(t.Context())
defer cancel()
tx, err := testDB.Begin(ctxTx)
if err != nil {
t.Fatalf("Error starting transaction: %v", err)
}
defer func() {
if err := tx.Rollback(ctxTx); err != nil {
t.Fatalf("Error rolling back transaction: %v", err)
}
}()
query, args, err := bob.Build(ctxTx, psql.Select(TrapCountByLocationID(random_int32(nil), []string{random_string(nil)})))
if err != nil {
t.Fatal(err)
}
rows, err := tx.QueryContext(ctxTx, query, args...)
if err != nil {
t.Fatal(err)
}
defer rows.Close()
columns, err := rows.Columns()
if err != nil {
t.Fatal(err)
}
if len(columns) != 5 {
t.Fatalf("expected %d columns, got %d", 5, len(columns))
}
if columns[0] != "trapdata_globalid" {
t.Fatalf("expected column %d to be %s, got %s", 0, "trapdata_globalid", columns[0])
}
if columns[1] != "trapdata_enddate" {
t.Fatalf("expected column %d to be %s, got %s", 1, "trapdata_enddate", columns[1])
}
if columns[2] != "total_females" {
t.Fatalf("expected column %d to be %s, got %s", 2, "total_females", columns[2])
}
if columns[3] != "total_males" {
t.Fatalf("expected column %d to be %s, got %s", 3, "total_males", columns[3])
}
if columns[4] != "total" {
t.Fatalf("expected column %d to be %s, got %s", 4, "total", columns[4])
}
})
}

View file

@ -0,0 +1,17 @@
-- TrapCountByLocationID
SELECT
td.loc_id AS trapdata_globalid,
td.enddatetime AS trapdata_enddate,
COALESCE(SUM(sa.females), 0) AS total_females,
COALESCE(SUM(sa.males), 0) AS total_males,
COALESCE(SUM(sa.total), 0) AS total
FROM
fs_trapdata td
LEFT JOIN
fs_speciesabundance sa ON td.globalid = sa.trapdata_id
WHERE
td.organization_id = $1
AND td.loc_id IN ($2)
GROUP BY
td.globalid, td.enddatetime;

View file

@ -0,0 +1,106 @@
// Code generated by BobGen psql v0.41.1. DO NOT EDIT.
// This file is meant to be re-generated in place and/or deleted at any time.
package sql
import (
"context"
_ "embed"
"io"
"iter"
"github.com/stephenafamo/bob"
"github.com/stephenafamo/bob/dialect/psql"
"github.com/stephenafamo/bob/dialect/psql/dialect"
"github.com/stephenafamo/bob/orm"
"github.com/stephenafamo/scan"
)
//go:embed traplocation_by_source_id.bob.sql
var formattedQueries_traplocation_by_source_id string
var trapLocationBySourceIDSQL = formattedQueries_traplocation_by_source_id[160:411]
type TrapLocationBySourceIDQuery = orm.ModQuery[*dialect.SelectQuery, trapLocationBySourceID, TrapLocationBySourceIDRow, []TrapLocationBySourceIDRow, trapLocationBySourceIDTransformer]
func TrapLocationBySourceID(OrganizationID int32, Globalid string) *TrapLocationBySourceIDQuery {
var expressionTypArgs trapLocationBySourceID
expressionTypArgs.OrganizationID = psql.Arg(OrganizationID)
expressionTypArgs.Globalid = psql.Arg(Globalid)
return &TrapLocationBySourceIDQuery{
Query: orm.Query[trapLocationBySourceID, TrapLocationBySourceIDRow, []TrapLocationBySourceIDRow, trapLocationBySourceIDTransformer]{
ExecQuery: orm.ExecQuery[trapLocationBySourceID]{
BaseQuery: bob.BaseQuery[trapLocationBySourceID]{
Expression: expressionTypArgs,
Dialect: dialect.Dialect,
QueryType: bob.QueryTypeSelect,
},
},
Scanner: func(context.Context, []string) (func(*scan.Row) (any, error), func(any) (TrapLocationBySourceIDRow, error)) {
return func(row *scan.Row) (any, error) {
var t TrapLocationBySourceIDRow
row.ScheduleScanByIndex(0, &t.TrapLocationGlobalid)
row.ScheduleScanByIndex(1, &t.Distance)
return &t, nil
}, func(v any) (TrapLocationBySourceIDRow, error) {
return *(v.(*TrapLocationBySourceIDRow)), nil
}
},
},
Mod: bob.ModFunc[*dialect.SelectQuery](func(q *dialect.SelectQuery) {
q.CombinedLimit.SetLimit(psql.Raw("4"))
q.AppendSelect(expressionTypArgs.subExpr(9, 90))
q.SetTable(expressionTypArgs.subExpr(98, 148))
q.AppendWhere(expressionTypArgs.subExpr(157, 202))
q.CombinedOrder.AppendOrder(expressionTypArgs.subExpr(214, 243))
}),
}
}
type TrapLocationBySourceIDRow = struct {
TrapLocationGlobalid string `db:"trap_location_globalid"`
Distance string `db:"distance"`
}
type trapLocationBySourceIDTransformer = bob.SliceTransformer[TrapLocationBySourceIDRow, []TrapLocationBySourceIDRow]
type trapLocationBySourceID struct {
OrganizationID bob.Expression
Globalid bob.Expression
}
func (o trapLocationBySourceID) args() iter.Seq[orm.ArgWithPosition] {
return func(yield func(arg orm.ArgWithPosition) bool) {
if !yield(orm.ArgWithPosition{
Name: "organizationID",
Start: 178,
Stop: 180,
Expression: o.OrganizationID,
}) {
return
}
if !yield(orm.ArgWithPosition{
Name: "globalid",
Start: 200,
Stop: 202,
Expression: o.Globalid,
}) {
return
}
}
}
func (o trapLocationBySourceID) raw(from, to int) string {
return trapLocationBySourceIDSQL[from:to]
}
func (o trapLocationBySourceID) subExpr(from, to int) bob.Expression {
return orm.ArgsToExpression(trapLocationBySourceIDSQL, from, to, o.args())
}
func (o trapLocationBySourceID) WriteSQL(ctx context.Context, w io.Writer, d bob.Dialect, start int) ([]any, error) {
return o.subExpr(0, len(trapLocationBySourceIDSQL)).WriteSQL(ctx, w, d, start)
}

View file

@ -0,0 +1,17 @@
-- Code generated by BobGen psql v0.41.1. DO NOT EDIT.
-- This file is meant to be re-generated in place and/or deleted at any time.
-- TrapLocationBySourceID
SELECT
tl.globalid AS trap_location_globalid,
ST_Distance(pl.geom, tl.geom) AS distance
FROM
fs_pointlocation pl
CROSS JOIN
fs_traplocation tl
WHERE
tl.organization_id = $1 AND
pl.globalid = $2
ORDER BY
ST_Distance(pl.geom, tl.geom)
LIMIT 4;

View file

@ -0,0 +1,99 @@
// Code generated by BobGen psql v0.41.1. DO NOT EDIT.
// This file is meant to be re-generated in place and/or deleted at any time.
package sql
import (
"context"
"fmt"
"strings"
"testing"
"github.com/google/go-cmp/cmp"
"github.com/stephenafamo/bob"
"github.com/stephenafamo/bob/dialect/psql"
testutils "github.com/stephenafamo/bob/test/utils"
)
func TestTrapLocationBySourceID(t *testing.T) {
t.Run("Base", func(t *testing.T) {
var sb strings.Builder
query := TrapLocationBySourceID(random_int32(nil), random_string(nil))
if _, err := query.WriteQuery(t.Context(), &sb, 1); err != nil {
t.Fatal(err)
}
if diff := cmp.Diff(trapLocationBySourceIDSQL, sb.String()); diff != "" {
t.Fatalf("unexpected result (-got +want):\n%s", diff)
}
})
t.Run("Mod", func(t *testing.T) {
var sb strings.Builder
query := TrapLocationBySourceID(random_int32(nil), random_string(nil))
if _, err := psql.Select(query).WriteQuery(t.Context(), &sb, 1); err != nil {
t.Fatal(err)
}
queryDiff, err := testutils.QueryDiff(trapLocationBySourceIDSQL, sb.String(), formatQuery)
if err != nil {
t.Fatal(err)
}
if queryDiff != "" {
fmt.Println(sb.String())
t.Fatalf("unexpected result (-got +want):\n%s", queryDiff)
}
})
t.Run("Scanning", func(t *testing.T) {
if testDB == nil {
t.Skip("skipping test, no DSN provided")
}
ctxTx, cancel := context.WithCancel(t.Context())
defer cancel()
tx, err := testDB.Begin(ctxTx)
if err != nil {
t.Fatalf("Error starting transaction: %v", err)
}
defer func() {
if err := tx.Rollback(ctxTx); err != nil {
t.Fatalf("Error rolling back transaction: %v", err)
}
}()
query, args, err := bob.Build(ctxTx, psql.Select(TrapLocationBySourceID(random_int32(nil), random_string(nil))))
if err != nil {
t.Fatal(err)
}
rows, err := tx.QueryContext(ctxTx, query, args...)
if err != nil {
t.Fatal(err)
}
defer rows.Close()
columns, err := rows.Columns()
if err != nil {
t.Fatal(err)
}
if len(columns) != 2 {
t.Fatalf("expected %d columns, got %d", 2, len(columns))
}
if columns[0] != "trap_location_globalid" {
t.Fatalf("expected column %d to be %s, got %s", 0, "trap_location_globalid", columns[0])
}
if columns[1] != "distance" {
t.Fatalf("expected column %d to be %s, got %s", 1, "distance", columns[1])
}
})
}

View file

@ -0,0 +1,14 @@
-- TrapLocationBySourceID
SELECT
tl.globalid AS trap_location_globalid,
ST_Distance(pl.geom, tl.geom) AS distance
FROM
fs_pointlocation pl
CROSS JOIN
fs_traplocation tl
WHERE
tl.organization_id = $1 AND
pl.globalid = $2
ORDER BY
ST_Distance(pl.geom, tl.geom)
LIMIT 4