Nobody had ever created a function like this one before. (#26)

Reviewed-on: rrise/reloading-manager#26
Co-authored-by: Ron Rise <ron@siteworxpro.com>
Co-committed-by: Ron Rise <ron@siteworxpro.com>
This commit is contained in:
2025-04-18 17:30:11 -04:00
committed by Siteworx Pro Gitea
parent 1ae280d785
commit eaa9b97baa
41 changed files with 1159 additions and 88 deletions

View File

@@ -2,15 +2,45 @@ package loads
import (
"context"
"fmt"
"git.siteworxpro.com/reloading-manager/backend/.gen/loading/public/table"
"git.siteworxpro.com/reloading-manager/backend/database"
"git.siteworxpro.com/reloading-manager/backend/handlers"
"git.siteworxpro.com/reloading-manager/backend/handlers/bullets"
"git.siteworxpro.com/reloading-manager/backend/handlers/primers"
"git.siteworxpro.com/reloading-manager/backend/models/loads"
"github.com/go-jet/jet/v2/postgres"
"github.com/jackc/pgx/v5/pgtype"
"github.com/labstack/echo/v4"
"net/http"
)
type row struct {
ID pgtype.UUID
Col float32
PowderGr float32
CartridgeID pgtype.UUID
CartridgeName string
CartridgeMeta []byte
BulletID pgtype.UUID
BulletName string
BulletDiameter int32
BulletWeight int32
BulletMeta []byte
BulletManufacturerName string
BulletManufacturerUrl pgtype.Text
PrimerID pgtype.UUID
PrimerName string
PrimerMeta []byte
PrimerManufacturerName string
PrimerManufacturerUrl pgtype.Text
PowderID pgtype.UUID
PowderName string
PowderMeta []byte
PowderManufacturerName string
PowderManufacturerUrl pgtype.Text
}
type loadResponseResults struct {
Id string `json:"id"`
Cartridge string `json:"cartridge"`
@@ -103,58 +133,42 @@ func Post(c echo.Context) error {
}
func Get(c echo.Context) error {
db := c.(*database.CustomContext).Db
defer db.Db.Close(context.Background())
cTotal := make(chan ResultChan[int64])
cResults := make(chan ResultChan[[]loadResponseResults])
go func(c chan ResultChan[int64]) {
go func(ch chan ResultChan[int64]) {
db := database.GetNewDatabase()
defer db.Db.Close(context.Background())
total, err := db.Loads.TotalLoads(context.Background())
q := getQuery(c, true)
sql, params := q.Sql()
var total int64
r := db.Db.QueryRow(context.Background(), sql, params...)
err := r.Scan(&total)
if err != nil {
c <- ResultChan[int64]{Err: err}
ch <- ResultChan[int64]{Err: err}
} else {
c <- ResultChan[int64]{Result: total}
ch <- ResultChan[int64]{Result: total}
}
}(cTotal)
go func(ch chan ResultChan[[]loadResponseResults]) {
db := database.GetNewDatabase()
rows, err := db.Loads.GetLoads(context.Background(), loads.GetLoadsParams{
Limit: handlers.ParseInt32WithDefault(c.QueryParam("limit"), 50),
Offset: handlers.ParseInt32WithDefault(c.QueryParam("offset"), 0),
defer db.Db.Close(context.Background())
OrderBy: "cartridge_name asc",
q := getQuery(c, false)
SearchCartridge: c.QueryParam("search_cartridge") != "",
Cartridge: c.QueryParam("search_cartridge"),
SearchBullet: c.QueryParam("search_bullet") != "",
Bullet: c.QueryParam("search_bullet") + "%",
SearchBulletManufacturer: c.QueryParam("search_bullet_manufacturer") != "",
BulletManufacturer: c.QueryParam("search_bullet_manufacturer") + "%",
SearchPrimer: c.QueryParam("search_primer") != "",
Primer: c.QueryParam("search_primer") + "%",
SearchPrimerManufacturer: c.QueryParam("search_primer_manufacturer") != "",
PrimeManufacturer: c.QueryParam("search_primer_manufacturer") + "%",
SearchPowder: c.QueryParam("search_powder") != "",
Powder: c.QueryParam("search_powder") + "%",
SearchPowderManufacturer: c.QueryParam("search_powder_manufacturer") != "",
PowderManufacturer: c.QueryParam("search_powder_manufacturer") + "%",
fmt.Println(q.DebugSql())
sql, params := q.Sql()
rows, err := db.Db.Query(context.Background(), sql, params...)
SearchCartridgeID: c.QueryParam("search_cartridge_id") != "",
CartridgeID: *handlers.ParseUuidOrEmpty(c.QueryParam("search_cartridge_id")),
SearchBulletID: c.QueryParam("search_bullet_id") != "",
BulletID: *handlers.ParseUuidOrEmpty(c.QueryParam("search_bullet_id")),
SearchPrimerID: c.QueryParam("search_primer_id") != "",
PrimerID: *handlers.ParseUuidOrEmpty(c.QueryParam("search_primer_id")),
SearchPowderID: c.QueryParam("search_powder_id") != "",
PowderID: *handlers.ParseUuidOrEmpty(c.QueryParam("search_powder_id")),
})
if err != nil {
ch <- ResultChan[[]loadResponseResults]{Err: err}
@@ -162,7 +176,44 @@ func Get(c echo.Context) error {
}
results := make([]loadResponseResults, 0)
for _, row := range rows {
for rows.Next() {
row := row{}
err = rows.Scan(
&row.ID,
&row.Col,
&row.PowderGr,
&row.CartridgeID,
&row.CartridgeName,
&row.CartridgeMeta,
&row.BulletID,
&row.BulletName,
&row.BulletDiameter,
&row.BulletWeight,
&row.BulletMeta,
&row.BulletManufacturerName,
&row.BulletManufacturerUrl,
&row.PrimerID,
&row.PrimerName,
&row.PrimerMeta,
&row.PrimerManufacturerName,
&row.PrimerManufacturerUrl,
&row.PowderID,
&row.PowderName,
&row.PowderMeta,
&row.PowderManufacturerName,
&row.PowderManufacturerUrl,
)
if err != nil {
ch <- ResultChan[[]loadResponseResults]{Err: err}
return
}
results = append(results, loadResponseResults{
Id: row.ID.String(),
Cartridge: row.CartridgeName,
@@ -213,3 +264,135 @@ func Get(c echo.Context) error {
return c.JSON(http.StatusOK, handlers.Response[loadResponse]{Status: http.StatusText(http.StatusOK), Payload: loadResponse{Total: int(total.Result), Results: results.Result}})
}
func getQuery(c echo.Context, countOnly bool) postgres.SelectStatement {
l := table.Loads.AS("l")
ctg := table.Cartridges.AS("c")
b := table.Bullets.AS("b")
bm := table.Manufacturers.AS("b_m")
p := table.Primers.AS("p")
pm := table.Manufacturers.AS("p_m")
pwd := table.Powders.AS("pw")
pwdm := table.Manufacturers.AS("pw_m")
tb := l.
INNER_JOIN(ctg, l.CartridgeID.EQ(ctg.ID)).
INNER_JOIN(b, l.BulletID.EQ(b.ID)).
INNER_JOIN(bm, b.ManufacturerID.EQ(bm.ID)).
INNER_JOIN(p, l.PrimerID.EQ(p.ID)).
INNER_JOIN(pm, p.ManufacturerID.EQ(pm.ID)).
INNER_JOIN(pwd, l.PowderID.EQ(pwd.ID)).
INNER_JOIN(pwdm, pwd.ManufacturerID.EQ(pwdm.ID))
var q postgres.SelectStatement
if countOnly {
q = tb.SELECT(postgres.COUNT(l.ID).AS("total"))
} else {
q = tb.SELECT(
// Load
l.ID.AS("id"),
l.Col.AS("col"),
l.PowderGr.AS("powder_gr"),
// Cartridge
ctg.ID.AS("cartridge_id"),
ctg.Name.AS("cartridge_name"),
ctg.Meta.AS("cartridge_meta"),
// Bullet
b.ID.AS("bullet_id"),
b.Name.AS("bullet_name"),
b.Diameter.AS("bullet_diameter"),
b.Weight.AS("bullet_weight"),
b.Meta.AS("bullet_meta"),
bm.Name.AS("bullet_manufacturer_name"),
bm.URL.AS("bullet_manufacturer_url"),
// Primer
p.ID.AS("primer_id"),
p.Name.AS("primer_name"),
p.Meta.AS("primer_meta"),
pm.Name.AS("primer_manufacturer_name"),
pm.URL.AS("primer_manufacturer_url"),
// Powder
pwd.ID.AS("powder_id"),
pwd.Name.AS("powder_name"),
pwd.Meta.AS("powder_meta"),
pwdm.Name.AS("powder_manufacturer_name"),
pwdm.URL.AS("powder_manufacturer_url"),
)
}
expressions := make([]postgres.BoolExpression, 0)
if c.QueryParam("search_cartridge") != "" {
expressions = append(expressions, ctg.Name.LIKE(postgres.String(c.QueryParam("search_cartridge")+"%")))
}
if c.QueryParam("search_bullet") != "" {
expressions = append(expressions, b.Name.LIKE(postgres.String(c.QueryParam("search_bullet")+"%")))
}
var where postgres.BoolExpression
if len(expressions) > 0 {
for _, expr := range expressions {
if where == nil {
where = expr
} else {
where = where.AND(expr)
}
}
}
if where != nil {
q = q.WHERE(where)
}
if countOnly {
return q
}
orderBy := c.QueryParam("sortField")
var sort postgres.Column
switch orderBy {
case "cartridge_name":
sort = ctg.Name
case "bullet_name":
sort = b.Name
case "bullet_manufacturer_name":
sort = bm.Name
case "primer_manufacturer_name":
sort = pm.Name
case "primer_name":
sort = p.Name
case "powder_manufacturer_name":
sort = pwdm.Name
case "powder_namd":
sort = pwd.Name
case "powder_grs":
sort = l.PowderGr
default:
sort = ctg.Name
}
if c.QueryParam("sortOrder") == "-1" {
q.ORDER_BY(sort.DESC())
} else {
q.ORDER_BY(sort.ASC())
}
limit := c.QueryParam("limit")
if limit == "" {
limit = "50"
}
offset := c.QueryParam("offset")
if offset == "" {
offset = "0"
}
q = q.LIMIT(handlers.ParseInt64OrDefault(limit, 50)).
OFFSET(handlers.ParseInt64OrDefault(offset, 0))
return q
}

View File

@@ -19,3 +19,12 @@ func ParseInt32WithDefault(s string, def int32) int32 {
return int32(sInt)
}
func ParseInt64OrDefault(s string, def int64) int64 {
sInt, err := strconv.ParseInt(s, 10, 64)
if err != nil {
return def
}
return sInt
}