No changes made

This commit is contained in:
2025-04-16 12:47:04 -04:00
commit 1ed3b0c2d4
98 changed files with 8857 additions and 0 deletions

35
backend/.gitlab-ci.yml Normal file
View File

@@ -0,0 +1,35 @@
stages:
- test
- build
variables:
IMAGE_URL: siteworxpro/
IMAGE_NAME: reloading-backend
Unit Tests:
stage: test
only:
- branches
image: siteworxpro/golang:1.24.0
before_script:
- go mod tidy
script:
- go test ./...
Build:
stage: build
dependencies:
- Unit Tests
only:
- master
image: docker:dind
before_script:
- docker login -u siteworxpro -p ${DOCKER_TOKEN}
script:
- TAG=${CI_COMMIT_REF_NAME}-${CI_COMMIT_SHORT_SHA}
- docker build -t ${IMAGE_NAME} .
- docker tag ${IMAGE_NAME}:latest ${IMAGE_URL}${IMAGE_NAME}:latest
- docker tag ${IMAGE_URL}${IMAGE_NAME}:latest ${IMAGE_URL}${IMAGE_NAME}:${TAG}
- docker push ${IMAGE_URL}${IMAGE_NAME}:${TAG}
- docker push ${IMAGE_URL}${IMAGE_NAME}:latest

19
backend/Dockerfile Normal file
View File

@@ -0,0 +1,19 @@
FROM siteworxpro/golang:1.24.0 AS build
WORKDIR /app
ARG CGO_ENABLED=0
ARG GOOS=linux
ARG GOPROXY=direct
ARG GOPRIVATE=git.s.int
ADD . .
RUN go mod tidy
RUN go build -o app
FROM scratch
COPY --from=build /app/app .
ENTRYPOINT ["/app"]

8
backend/README.md Normal file
View File

@@ -0,0 +1,8 @@
```shell
docker run -v $(pwd)/postgres:/var/lib/postgresql/data \
-e POSTGRES_DB=loading \
-e POSTGRES_PASSWORD=password \
--rm --name postgres \
-p 5432:5432 \
-d scr.siteworxpro.com/library/postgres:17
```

63
backend/database/conn.go Normal file
View File

@@ -0,0 +1,63 @@
package database
import (
"context"
"fmt"
"git.s.int/packages/go/utilities/Env"
"git.s.int/reloading-manager/backend/models/bullets"
"git.s.int/reloading-manager/backend/models/loads"
"git.s.int/reloading-manager/backend/models/manufacturer"
"git.s.int/reloading-manager/backend/models/powder"
"git.s.int/reloading-manager/backend/models/primers"
"github.com/jackc/pgx/v5"
"log"
)
const (
DbHost Env.EnvironmentVariable = "DB_HOST"
DbDatabase Env.EnvironmentVariable = "DB_DATABASE"
DbUser Env.EnvironmentVariable = "DB_USER"
DbPassword Env.EnvironmentVariable = "DB_PASSWORD"
)
type Database struct {
Db *pgx.Conn
connected bool
databaseName string
Bullets *bullets.Queries
Manufacturer *manufacturer.Queries
Powder *powder.Queries
Primer *primers.Queries
Loads *loads.Queries
}
func (*Database) DSN() string {
dbHost := DbHost.GetEnvString("localhost")
dbDatabase := DbDatabase.GetEnvString("loading")
dbUser := DbUser.GetEnvString("postgres")
dbPassword := DbPassword.GetEnvString("password")
extraParams := "?sslmode=disable"
return fmt.Sprintf("postgres://%s:%s@%s:5432/%s%s", dbUser, dbPassword, dbHost, dbDatabase, extraParams)
}
func GetNewDatabase() *Database {
var dbSingleton Database
conn, dbErr := pgx.Connect(context.Background(), dbSingleton.DSN())
if dbErr != nil {
log.Fatal(dbErr)
}
dbSingleton.Db = conn
dbSingleton.connected = true
dbSingleton.databaseName = DbDatabase.GetEnvString("loading")
dbSingleton.Bullets = bullets.New(dbSingleton.Db)
dbSingleton.Manufacturer = manufacturer.New(dbSingleton.Db)
dbSingleton.Powder = powder.New(dbSingleton.Db)
dbSingleton.Primer = primers.New(dbSingleton.Db)
dbSingleton.Loads = loads.New(dbSingleton.Db)
return &dbSingleton
}

View File

@@ -0,0 +1,25 @@
package database
import (
"github.com/labstack/echo/v4"
)
type CustomContext struct {
echo.Context
Db *Database
}
func CreateDatabaseMiddleware() echo.MiddlewareFunc {
return func(next echo.HandlerFunc) echo.HandlerFunc {
return func(c echo.Context) error {
cc := &CustomContext{
Context: c,
Db: GetNewDatabase(),
}
res := next(cc)
return res
}
}
}

View File

@@ -0,0 +1,34 @@
package database
import (
"database/sql"
_ "github.com/go-sql-driver/mysql"
"github.com/golang-migrate/migrate"
"github.com/golang-migrate/migrate/database/postgres"
_ "github.com/golang-migrate/migrate/source/file"
"log"
)
func (db *Database) Migrate() {
sqlDB, err := sql.Open("postgres", db.DSN())
driver, err := postgres.WithInstance(sqlDB, &postgres.Config{})
if err != nil {
log.Fatal(err)
}
m, err := migrate.NewWithDatabaseInstance(
"file://./migrations",
db.databaseName,
driver,
)
if err != nil {
log.Fatal(err)
}
err = m.Up()
if err != nil && err.Error() != "no change" {
log.Fatal(err)
}
}

45
backend/go.mod Normal file
View File

@@ -0,0 +1,45 @@
module git.s.int/reloading-manager/backend
go 1.24.0
require (
git.s.int/packages/go/utilities v1.2.2
github.com/go-playground/validator v9.31.0+incompatible
github.com/go-sql-driver/mysql v1.9.1
github.com/golang-migrate/migrate v3.5.4+incompatible
github.com/google/uuid v1.6.0
github.com/jackc/pgx/v5 v5.7.4
github.com/labstack/echo/v4 v4.13.3
github.com/labstack/gommon v0.4.2
)
require (
filippo.io/edwards25519 v1.1.0 // indirect
github.com/Microsoft/go-winio v0.6.1 // indirect
github.com/distribution/reference v0.6.0 // indirect
github.com/docker/distribution v2.8.3+incompatible // indirect
github.com/docker/docker v24.0.5+incompatible // indirect
github.com/docker/go-connections v0.4.0 // indirect
github.com/docker/go-units v0.5.0 // indirect
github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang-jwt/jwt v3.2.2+incompatible // indirect
github.com/jackc/pgpassfile v1.0.0 // indirect
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect
github.com/leodido/go-urn v1.4.0 // indirect
github.com/lib/pq v1.10.9 // indirect
github.com/mattn/go-colorable v0.1.14 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/opencontainers/image-spec v1.0.2 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect
github.com/valyala/fasttemplate v1.2.2 // indirect
golang.org/x/crypto v0.36.0 // indirect
golang.org/x/net v0.38.0 // indirect
golang.org/x/sys v0.31.0 // indirect
golang.org/x/text v0.23.0 // indirect
golang.org/x/time v0.11.0 // indirect
gopkg.in/go-playground/assert.v1 v1.2.1 // indirect
)

152
backend/go.sum Normal file
View File

@@ -0,0 +1,152 @@
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
git.s.int/packages/go/utilities v1.2.2 h1:IXKdrTgRc7tnDUB4sOWD/kjwgw9luUzvsaPzX+Dhm7Y=
git.s.int/packages/go/utilities v1.2.2/go.mod h1:1nIS3PzUaLiNBBkyme408XbI725PiureeTV7iBXfUI0=
github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow=
github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk=
github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk=
github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
github.com/docker/docker v24.0.5+incompatible h1:WmgcE4fxyI6EEXxBRxsHnZXrO1pQ3smi0k/jho4HLeY=
github.com/docker/docker v24.0.5+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ=
github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
github.com/go-playground/validator v9.31.0+incompatible h1:UA72EPEogEnq76ehGdEDp4Mit+3FDh548oRqwVgNsHA=
github.com/go-playground/validator v9.31.0+incompatible/go.mod h1:yrEkQXlcI+PugkyDjY2bRrL/UBU4f3rvrgkN3V8JEig=
github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y=
github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg=
github.com/go-sql-driver/mysql v1.9.1 h1:FrjNGn/BsJQjVRuSa8CBrM5BWA9BWoXXat3KrtSb/iI=
github.com/go-sql-driver/mysql v1.9.1/go.mod h1:qn46aNg1333BRMNU69Lq93t8du/dwxI64Gl8i5p1WMU=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY=
github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
github.com/golang-migrate/migrate v3.5.4+incompatible h1:R7OzwvCJTCgwapPCiX6DyBiu2czIUMDCB118gFTKTUA=
github.com/golang-migrate/migrate v3.5.4+incompatible/go.mod h1:IsVUlFN5puWOmXrqjgGUfIRIbU7mr8oNBE2tyERd9Wk=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
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/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo=
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
github.com/jackc/pgx/v5 v5.7.3 h1:PO1wNKj/bTAwxSJnO1Z4Ai8j4magtqg2SLNjEDzcXQo=
github.com/jackc/pgx/v5 v5.7.3/go.mod h1:ncY89UGWxg82EykZUwSpUKEfccBGGYq1xjrOpsbsfGQ=
github.com/jackc/pgx/v5 v5.7.4 h1:9wKznZrhWa2QiHL+NjTSPP6yjl3451BX3imWDnokYlg=
github.com/jackc/pgx/v5 v5.7.4/go.mod h1:ncY89UGWxg82EykZUwSpUKEfccBGGYq1xjrOpsbsfGQ=
github.com/jackc/puddle/v2 v2.2.2 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo=
github.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/labstack/echo/v4 v4.12.0 h1:IKpw49IMryVB2p1a4dzwlhP1O2Tf2E0Ir/450lH+kI0=
github.com/labstack/echo/v4 v4.12.0/go.mod h1:UP9Cr2DJXbOK3Kr9ONYzNowSh7HP0aG0ShAyycHSJvM=
github.com/labstack/echo/v4 v4.13.3 h1:pwhpCPrTl5qry5HRdM5FwdXnhXSLSY+WE+YQSeCaafY=
github.com/labstack/echo/v4 v4.13.3/go.mod h1:o90YNEeQWjDozo584l7AwhJMHN0bOC4tAfg+Xox9q5g=
github.com/labstack/gommon v0.4.2 h1:F8qTUNXgG1+6WQmqoUWnz8WiEU60mXVVw0P4ht1WRA0=
github.com/labstack/gommon v0.4.2/go.mod h1:QlUFxVM+SNXhDL/Z7YhocGIBYOiwB0mXm1+1bAPHPyU=
github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q=
github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4=
github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE=
github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
github.com/opencontainers/image-spec v1.0.2 h1:9yCKha/T5XdGtO0q9Q9a6T5NUCsTn/DrBg0D7ufOcFM=
github.com/opencontainers/image-spec v1.0.2/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo=
github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U=
golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34=
golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA=
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys=
golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE=
golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8=
golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ=
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik=
golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY=
golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4=
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/time v0.11.0 h1:/bpjEDfN9tkoN/ryeYHnv5hcMlc8ncjMcM4XBk5NWV0=
golang.org/x/time v0.11.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg=
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/go-playground/assert.v1 v1.2.1 h1:xoYuJVE7KT85PYWrN730RguIQO0ePzVRfFMXadIrXTM=
gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

View File

@@ -0,0 +1,292 @@
package bullets
import (
"context"
"encoding/json"
"git.s.int/reloading-manager/backend/database"
"git.s.int/reloading-manager/backend/handlers"
"git.s.int/reloading-manager/backend/models/bullets"
"github.com/labstack/echo/v4"
"net/http"
"strconv"
)
type BulletResponse struct {
Id string `json:"id"`
Name string `json:"name"`
Diameter int32 `json:"diameter"`
Weight int32 `json:"weight"`
Manufacturer handlers.Manufacturer `json:"manufacturer"`
}
func Photo(c echo.Context) error {
db := c.(*database.CustomContext).Db
defer db.Db.Close(context.Background())
id := c.Param("id")
uid := handlers.ParseUuidOrBadRequest(c, id)
if uid == nil {
return nil
}
byId, err := db.Bullets.GetBulletById(context.Background(), *uid)
if err != nil {
return echo.NewHTTPError(http.StatusNotFound, "Not found")
}
mime := http.DetectContentType(byId.Photo)
c.Response().Header().Set("Content-Type", mime)
c.Response().Header().Set("Cache-Control", "no-cache, no-store, must-revalidate")
c.Response().Header().Set("Pragma", "no-cache")
c.Response().Header().Set("Expires", "0")
_, err = c.Response().Write(byId.Photo)
return err
}
func Delete(c echo.Context) error {
db := c.(*database.CustomContext).Db
defer db.Db.Close(context.Background())
id := c.Param("id")
uid := handlers.ParseUuidOrBadRequest(c, id)
if uid == nil {
return nil
}
err := db.Bullets.DeleteBullet(context.Background(), *uid)
if err != nil {
return err
}
return c.JSON(http.StatusOK, handlers.Response[string]{})
}
func Put(c echo.Context) error {
db := c.(*database.CustomContext).Db
defer db.Db.Close(context.Background())
id := c.Param("id")
uid := handlers.ParseUuidOrBadRequest(c, id)
if uid == nil {
return nil
}
byId, err := db.Bullets.GetBulletById(context.Background(), *uid)
if err != nil {
return echo.NewHTTPError(http.StatusNotFound, "Not found")
}
file, err := c.FormFile("photo")
var fileData []byte
if err == nil {
handler, err := file.Open()
if err != nil {
return err
}
buf := make([]byte, file.Size)
_, _ = handler.Read(buf)
fileData = buf
} else {
fileData = byId.Photo
}
var meta json.RawMessage = []byte(c.FormValue("meta"))
if len(meta) == 0 {
meta = []byte("{}")
}
weight, _ := strconv.ParseInt(c.FormValue("weight"), 10, 32)
diameter, _ := strconv.ParseInt(c.FormValue("diameter"), 10, 32)
manufacturerId := c.FormValue("manufacturer_id")
manufacturerUid := handlers.ParseUuidOrBadRequest(c, manufacturerId)
if manufacturerUid == nil {
return nil
}
name := c.FormValue("name")
if name == "" {
_ = c.JSON(http.StatusBadRequest, struct {
Message string `json:"message"`
}{
Message: "Name is required.",
})
return nil
}
manufacturer, err := db.Manufacturer.GetById(context.Background(), *manufacturerUid)
if err != nil {
_ = c.JSON(http.StatusBadRequest, struct {
Message string `json:"message"`
}{
Message: "Invalid Manufacturer ID",
})
return nil
}
err = db.Bullets.UpdateBullet(context.Background(), bullets.UpdateBulletParams{
Name: name,
Weight: int32(weight),
Diameter: int32(diameter),
Photo: fileData,
Meta: meta,
ManufacturerID: manufacturer.ID,
ID: byId.ID,
})
if err != nil {
return err
}
return nil
}
func Get(c echo.Context) error {
db := c.(*database.CustomContext).Db
defer db.Db.Close(context.Background())
if c.Param("id") != "" {
id := c.Param("id")
uid := handlers.ParseUuidOrBadRequest(c, id)
if uid == nil {
return nil
}
byId, err := db.Bullets.GetBulletById(context.Background(), *uid)
if err != nil {
return echo.NewHTTPError(http.StatusNotFound, "Not found")
}
response := handlers.Response[BulletResponse]{
Status: http.StatusText(http.StatusOK),
Payload: BulletResponse{
Id: uid.String(),
Name: byId.Name,
Diameter: byId.Diameter,
Weight: byId.Weight,
Manufacturer: handlers.Manufacturer{Id: byId.ManufactuererID.String(), Name: byId.ManufacutuerName, Url: byId.ManufacturerUrl.String},
},
}
return c.JSON(http.StatusOK, response)
}
bulletList, err := db.Bullets.ForPage(context.Background(), bullets.ForPageParams{
Limit: 100,
Offset: 0,
})
if bulletList == nil {
bulletList = make([]bullets.ForPageRow, 0)
}
var payload = make([]BulletResponse, 0)
for _, bullet := range bulletList {
payload = append(payload, BulletResponse{
Id: bullet.ID.String(),
Name: bullet.Name,
Weight: bullet.Weight,
Diameter: bullet.Diameter,
Manufacturer: handlers.Manufacturer{Id: bullet.ManufacturerID.String(), Name: bullet.ManufacturerName, Url: bullet.ManufacturerUrl.String},
})
}
if err != nil {
return err
}
err = c.JSON(http.StatusOK, handlers.Response[[]BulletResponse]{
Payload: payload,
Status: "OK",
})
if err != nil {
return err
}
return nil
}
func Post(c echo.Context) error {
file, err := c.FormFile("photo")
if err != nil {
c.Logger().Error(err)
_ = c.JSON(http.StatusBadRequest, struct {
Message string `json:"message"`
}{
Message: "No file provided",
})
return nil
}
handler, err := file.Open()
if err != nil {
return err
}
buf := make([]byte, file.Size)
_, _ = handler.Read(buf)
weight, _ := strconv.ParseInt(c.FormValue("weight"), 10, 32)
diameter, _ := strconv.ParseInt(c.FormValue("diameter"), 10, 32)
manufacturerId := c.FormValue("manufacturer_id")
name := c.FormValue("name")
if name == "" {
_ = c.JSON(http.StatusBadRequest, struct {
Message string `json:"message"`
}{
Message: "Name is required.",
})
return nil
}
db := c.(*database.CustomContext).Db
defer db.Db.Close(context.Background())
manufacturerUid := handlers.ParseUuidOrBadRequest(c, manufacturerId)
if manufacturerUid == nil {
return nil
}
manufacturer, err := db.Manufacturer.GetById(context.Background(), *manufacturerUid)
if err != nil {
_ = c.JSON(http.StatusBadRequest, struct {
Message string `json:"message"`
}{
Message: "Invalid Manufacturer ID",
})
return nil
}
var meta json.RawMessage = []byte(c.FormValue("meta"))
if len(meta) == 0 {
meta = []byte("{}")
}
id, err := db.Bullets.AddBullet(context.Background(), bullets.AddBulletParams{
Name: name,
Weight: int32(weight),
Diameter: int32(diameter),
Photo: buf,
Meta: meta,
ManufacturerID: manufacturer.ID,
})
if err != nil {
return err
}
err = c.JSON(http.StatusAccepted, handlers.Response[string]{
Status: http.StatusText(http.StatusAccepted),
Payload: id.String(),
})
if err != nil {
return err
}
return nil
}

View File

@@ -0,0 +1,96 @@
package cartridge
import (
"context"
"encoding/json"
"git.s.int/reloading-manager/backend/database"
"git.s.int/reloading-manager/backend/handlers"
"git.s.int/reloading-manager/backend/models/loads"
"github.com/labstack/echo/v4"
"net/http"
)
type response struct {
Id string `json:"id"`
Name string `json:"name"`
}
type postRequest struct {
Name string `json:"name"`
Meta string `json:"meta"`
}
func Get(c echo.Context) error {
db := c.(*database.CustomContext).Db
defer db.Db.Close(context.Background())
cartridges, err := db.Loads.GetCartridges(context.Background())
if err != nil {
return echo.NewHTTPError(http.StatusInternalServerError, err.Error())
}
var res = make([]response, 0)
for _, cartridge := range cartridges {
res = append(res, response{
Id: cartridge.ID.String(),
Name: cartridge.Name,
})
}
return c.JSON(http.StatusOK, handlers.Response[[]response]{
Payload: res,
Status: http.StatusText(http.StatusOK),
})
}
func Post(c echo.Context) error {
db := c.(*database.CustomContext).Db
defer db.Db.Close(context.Background())
req := postRequest{}
err := c.Bind(&req)
if err != nil {
return echo.NewHTTPError(http.StatusBadRequest, err.Error())
}
if req.Name == "" {
return echo.NewHTTPError(http.StatusBadRequest, "name is required")
}
var meta json.RawMessage
if req.Meta != "" {
meta = []byte(req.Meta)
} else {
meta = []byte("{}")
}
retId, err := db.Loads.CreateCartridge(context.Background(), loads.CreateCartridgeParams{
Name: req.Name,
Meta: meta,
})
if err != nil {
return handlers.BadRequest(c, "already exists")
}
return c.JSON(http.StatusOK, map[string]string{"id": retId.String()})
}
func Delete(c echo.Context) error {
db := c.(*database.CustomContext).Db
defer db.Db.Close(context.Background())
uid := handlers.ParseUuidOrBadRequest(c, c.Param("id"))
if uid == nil {
return nil
}
err := db.Loads.DeleteCartridge(context.Background(), *uid)
if err != nil {
return err
}
return c.NoContent(http.StatusOK)
}

29
backend/handlers/file.go Normal file
View File

@@ -0,0 +1,29 @@
package handlers
import (
"github.com/labstack/echo/v4"
"net/http"
)
func ReadFile(c echo.Context, formName string) ([]byte, error) {
file, err := c.FormFile(formName)
if err != nil {
c.Logger().Error(err)
_ = c.JSON(http.StatusBadRequest, struct {
Message string `json:"message"`
}{
Message: "No file provided",
})
return nil, err
}
handler, err := file.Open()
if err != nil {
return nil, err
}
buf := make([]byte, file.Size)
_, _ = handler.Read(buf)
return buf, nil
}

View File

@@ -0,0 +1,215 @@
package loads
import (
"context"
"git.s.int/reloading-manager/backend/database"
"git.s.int/reloading-manager/backend/handlers"
"git.s.int/reloading-manager/backend/handlers/bullets"
"git.s.int/reloading-manager/backend/handlers/primers"
"git.s.int/reloading-manager/backend/models/loads"
"github.com/labstack/echo/v4"
"net/http"
)
type loadResponseResults struct {
Id string `json:"id"`
Cartridge string `json:"cartridge"`
Col float32 `json:"col"`
Powder handlers.Powder `json:"powder"`
PowderGr float32 `json:"powder_gr"`
Primer primers.PrimerResponse `json:"primer"`
Bullet bullets.BulletResponse `json:"bullet"`
}
type loadResponse struct {
Total int `json:"total"`
Results []loadResponseResults `json:"results"`
}
type ResultChan[T any] struct {
Result T
Err error
}
func Post(c echo.Context) error {
db := c.(*database.CustomContext).Db
defer db.Db.Close(context.Background())
cartridgeID, err := handlers.ParseUuid(c.FormValue("cartridge_id"))
if err != nil {
return handlers.BadRequest(c, "cartridge_id is not a valid UUID")
}
powderId, err := handlers.ParseUuid(c.FormValue("powder_id"))
if err != nil {
return handlers.BadRequest(c, "powder_id is not a valid UUID")
}
primerId, err := handlers.ParseUuid(c.FormValue("primer_id"))
if err != nil {
return handlers.BadRequest(c, "primer_id is not a valid UUID")
}
bulletId, err := handlers.ParseUuid(c.FormValue("bullet_id"))
if err != nil {
return handlers.BadRequest(c, "bullet_id is not a valid UUID")
}
file, err := handlers.ReadFile(c, "photo")
if err != nil {
return handlers.BadRequest(c, "photo is not valid")
}
meta := c.FormValue("meta")
if meta == "" {
meta = "{}"
}
powderGr := c.FormValue("powder_gr")
if powderGr == "" {
return handlers.BadRequest(c, "powder_gr is not valid")
}
powderGrFl, err := handlers.ParseFloat32(powderGr)
if err != nil {
return handlers.BadRequest(c, "powder_gr is not valid")
}
col := c.FormValue("col")
if col == "" {
return handlers.BadRequest(c, "col is not valid")
}
colFl, err := handlers.ParseFloat32(col)
if err != nil {
return handlers.BadRequest(c, "col is not valid")
}
uid, err := db.Loads.CreateLoad(context.Background(), loads.CreateLoadParams{
CartridgeID: *cartridgeID,
Col: colFl,
PowderID: *powderId,
PowderGr: powderGrFl,
PrimerID: *primerId,
BulletID: *bulletId,
Photo: file,
Meta: []byte(meta),
})
if err != nil {
return err
}
return c.JSON(http.StatusCreated, handlers.Response[string]{Payload: uid.String()})
}
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]) {
db := database.GetNewDatabase()
defer db.Db.Close(context.Background())
total, err := db.Loads.TotalLoads(context.Background())
if err != nil {
c <- ResultChan[int64]{Err: err}
} else {
c <- ResultChan[int64]{Result: total}
}
}(cTotal)
go func(ch chan ResultChan[[]loadResponseResults]) {
rows, err := db.Loads.GetLoads(context.Background(), loads.GetLoadsParams{
Limit: handlers.ParseInt32WithDefault(c.QueryParam("limit"), 50),
Offset: handlers.ParseInt32WithDefault(c.QueryParam("offset"), 0),
OrderBy: "cartridge_name asc",
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") + "%",
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}
return
}
results := make([]loadResponseResults, 0)
for _, row := range rows {
results = append(results, loadResponseResults{
Id: row.ID.String(),
Cartridge: row.CartridgeName,
Col: row.Col,
Powder: handlers.Powder{
Id: row.PowderID.String(),
Name: row.PowderName,
Meta: string(row.PowderMeta),
Manufacturer: handlers.Manufacturer{
Name: row.PowderManufacturerName,
Url: row.PowderManufacturerUrl.String,
},
},
PowderGr: row.PowderGr,
Primer: primers.PrimerResponse{
ID: row.PrimerID.String(),
Name: row.PrimerName,
Manufacturer: handlers.Manufacturer{
Name: row.PrimerManufacturerName,
Url: row.PrimerManufacturerUrl.String,
},
},
Bullet: bullets.BulletResponse{
Id: row.BulletID.String(),
Name: row.BulletName,
Diameter: row.BulletDiameter,
Weight: row.BulletWeight,
Manufacturer: handlers.Manufacturer{
Name: row.BulletManufacturerName,
Url: row.BulletManufacturerUrl.String,
},
},
})
}
ch <- ResultChan[[]loadResponseResults]{Result: results}
}(cResults)
total := <-cTotal
if total.Err != nil {
return total.Err
}
results := <-cResults
if results.Err != nil {
return results.Err
}
return c.JSON(http.StatusOK, handlers.Response[loadResponse]{Status: http.StatusText(http.StatusOK), Payload: loadResponse{Total: int(total.Result), Results: results.Result}})
}

View File

@@ -0,0 +1,167 @@
package manufacturer
import (
"context"
"encoding/json"
"git.s.int/reloading-manager/backend/database"
"git.s.int/reloading-manager/backend/handlers"
"git.s.int/reloading-manager/backend/models/manufacturer"
"github.com/google/uuid"
"github.com/jackc/pgx/v5/pgtype"
"github.com/labstack/echo/v4"
"net/http"
)
type manufacturerResponse struct {
Id string `json:"id"`
Name string `json:"name"`
Url string `json:"url"`
CreatedAt string `json:"created_at"`
}
func Get(c echo.Context) error {
db := c.(*database.CustomContext).Db
defer db.Db.Close(context.Background())
if c.Param("id") != "" {
id := c.Param("id")
uid := handlers.ParseUuidOrBadRequest(c, id)
if uid == nil {
return nil
}
byId, err := db.Manufacturer.GetById(context.Background(), *uid)
if err != nil {
return echo.NewHTTPError(http.StatusNotFound, "Not found")
}
response := handlers.Response[manufacturerResponse]{
Status: http.StatusText(http.StatusOK),
Payload: manufacturerResponse{
Id: byId.ID.String(),
Name: byId.Name,
Url: byId.Url.String,
CreatedAt: byId.CreatedAt.Time.Format(handlers.DateFormat),
},
}
return c.JSON(http.StatusOK, response)
}
all, err := db.Manufacturer.GetAll(context.Background())
if err != nil {
return err
}
var payload []manufacturerResponse
for _, m := range all {
payload = append(payload, manufacturerResponse{
Id: m.ID.String(),
Name: m.Name,
Url: m.Url.String,
CreatedAt: m.CreatedAt.Time.Format(handlers.DateFormat),
})
}
response := handlers.Response[[]manufacturerResponse]{
Status: http.StatusText(http.StatusOK),
Payload: payload,
}
return c.JSON(http.StatusOK, response)
}
func Delete(c echo.Context) error {
db := c.(*database.CustomContext).Db
defer db.Db.Close(context.Background())
id := c.Param("id")
uid := handlers.ParseUuidOrBadRequest(c, id)
if uid == nil {
return nil
}
_, err := db.Manufacturer.GetById(context.Background(), *uid)
if err != nil {
return echo.NewHTTPError(http.StatusNotFound, "Not found")
}
err = db.Manufacturer.DeleteById(context.Background(), *uid)
if err != nil {
return echo.NewHTTPError(http.StatusBadRequest, "Cannot delete manufacturer")
}
return c.NoContent(http.StatusNoContent)
}
func Post(c echo.Context) error {
db := c.(*database.CustomContext).Db
defer db.Db.Close(context.Background())
if c.Param("id") != "" {
id := c.Param("id")
uid := handlers.ParseUuidOrBadRequest(c, id)
if uid == nil {
return nil
}
_, err := db.Manufacturer.GetById(context.Background(), *uid)
if err != nil {
return echo.NewHTTPError(http.StatusNotFound, "Not found")
}
jsonMap := make(map[string]interface{})
_ = json.NewDecoder(c.Request().Body).Decode(&jsonMap)
if jsonMap["name"] == "" {
return handlers.BadRequest(c, "Name is required.")
}
err = db.Manufacturer.UpdateManufacturer(context.Background(), manufacturer.UpdateManufacturerParams{
Name: jsonMap["name"].(string),
Url: pgtype.Text{
String: jsonMap["url"].(string),
Valid: true,
},
ID: *uid,
})
if err != nil {
return err
}
return nil
}
newUuid := uuid.New().String()
uid, _ := handlers.ParseUuid(newUuid)
jsonMap := make(map[string]interface{})
_ = json.NewDecoder(c.Request().Body).Decode(&jsonMap)
if jsonMap["name"] == nil || jsonMap["name"] == "" {
return handlers.BadRequest(c, "Name is required.")
}
var url string
if jsonMap["url"] != nil {
url = jsonMap["url"].(string)
}
err := db.Manufacturer.CreateManufacturer(context.Background(), manufacturer.CreateManufacturerParams{
ID: *uid,
Name: jsonMap["name"].(string),
Url: pgtype.Text{
String: url,
Valid: true,
},
})
if err != nil {
return err
}
return c.JSON(http.StatusAccepted, handlers.Response[string]{
Status: http.StatusText(http.StatusAccepted),
Payload: newUuid,
})
}

View File

@@ -0,0 +1,21 @@
package handlers
import "strconv"
func ParseFloat32(v string) (float32, error) {
fl, err := strconv.ParseFloat(v, 32)
if err != nil {
return 0, err
}
return float32(fl), nil
}
func ParseInt32WithDefault(s string, def int32) int32 {
sInt, err := strconv.ParseInt(s, 10, 32)
if err != nil {
return def
}
return int32(sInt)
}

View File

@@ -0,0 +1,217 @@
package powder
import (
"context"
"encoding/json"
"git.s.int/reloading-manager/backend/database"
"git.s.int/reloading-manager/backend/handlers"
"git.s.int/reloading-manager/backend/models/powder"
"github.com/google/uuid"
"github.com/labstack/echo/v4"
"net/http"
)
func Photo(c echo.Context) error {
db := c.(*database.CustomContext).Db
defer db.Db.Close(context.Background())
id := c.Param("id")
uid, err := handlers.ParseUuid(id)
if err != nil {
return handlers.BadRequest(c, "Invalid UUID")
}
byId, err := db.Powder.GetPowderById(context.Background(), *uid)
if err != nil {
return echo.NewHTTPError(http.StatusNotFound, "Not found")
}
mime := http.DetectContentType(byId.Photo)
c.Response().Header().Set("Content-Type", mime)
c.Response().Header().Set("Cache-Control", "no-cache, no-store, must-revalidate")
c.Response().Header().Set("Pragma", "no-cache")
c.Response().Header().Set("Expires", "0")
_, err = c.Response().Write(byId.Photo)
return err
}
func Delete(c echo.Context) error {
id := c.Param("id")
db := c.(*database.CustomContext).Db
defer db.Db.Close(context.Background())
uid, err := handlers.ParseUuid(id)
if err != nil {
return handlers.BadRequest(c, "Invalid UUID")
}
err = db.Powder.DeletePowder(context.Background(), *uid)
if err != nil {
return err
}
return c.JSON(http.StatusOK, handlers.Response[string]{})
}
func Post(c echo.Context) error {
db := c.(*database.CustomContext).Db
defer db.Db.Close(context.Background())
if c.Param("id") != "" {
id := c.Param("id")
uid, err := handlers.ParseUuid(id)
if err != nil {
return handlers.BadRequest(c, "Invalid UUID")
}
p, err := db.Powder.GetPowderById(context.Background(), *uid)
if err != nil {
return handlers.NotFound(c, "Not found")
}
file, _ := c.FormFile("photo")
if file != nil {
handler, _ := file.Open()
buf := make([]byte, file.Size)
_, _ = handler.Read(buf)
p.Photo = buf
}
if c.FormValue("name") != "" {
p.Name = c.FormValue("name")
}
muid, err := handlers.ParseUuid(c.FormValue("manufacturer_id"))
if err != nil {
return handlers.BadRequest(c, "Invalid UUID")
}
if c.FormValue("manufacturer_id") != "" {
p.ManufacturerID = *muid
}
metaString := c.FormValue("meta")
if metaString == "" {
metaString = string(p.Meta)
}
err = db.Powder.UpdatePowder(context.Background(), powder.UpdatePowderParams{
ID: p.ID,
Name: p.Name,
ManufacturerID: p.ManufacturerID,
Photo: p.Photo,
Meta: []byte(metaString),
})
if err != nil {
return err
}
return c.JSON(http.StatusOK, handlers.Response[string]{})
}
buf, err := handlers.ReadFile(c, "photo")
if err != nil {
return err
}
newUuid := uuid.New().String()
pgUuid, _ := handlers.ParseUuid(newUuid)
mfUid, _ := handlers.ParseUuid(c.FormValue("manufacturer_id"))
jsonMap := make(map[string]interface{})
jsonMap["name"] = c.FormValue("name")
if jsonMap["name"] == nil || jsonMap["name"] == "" {
return handlers.BadRequest(c, "Name is required.")
}
jsonMap["manufacturer_id"] = c.FormValue("manufacturer_id")
if jsonMap["manufacturer_id"] == nil || jsonMap["manufacturer_id"] == "" {
return handlers.BadRequest(c, "manufacturer_id is required.")
}
metaString := c.FormValue("meta")
if metaString == "" {
metaString = "{}"
}
var meta json.RawMessage = []byte(metaString)
err = db.Powder.InsertPowder(context.Background(), powder.InsertPowderParams{
ID: *pgUuid,
Name: jsonMap["name"].(string),
ManufacturerID: *mfUid,
Meta: meta,
Photo: buf,
})
if err != nil {
return err
}
return c.JSON(http.StatusCreated, handlers.Response[struct {
Id string `json:"id"`
}]{
Status: http.StatusText(http.StatusCreated),
Payload: struct {
Id string `json:"id"`
}{Id: newUuid},
})
}
func Get(c echo.Context) error {
db := c.(*database.CustomContext).Db
defer db.Db.Close(context.Background())
if c.Param("id") != "" {
id := c.Param("id")
uid, err := handlers.ParseUuid(id)
if err != nil {
return handlers.BadRequest(c, "Invalid UUID")
}
p, err := db.Powder.GetPowderById(context.Background(), *uid)
if err != nil {
return handlers.BadRequest(c, "Not found")
}
response := handlers.Response[handlers.Powder]{
Payload: handlers.Powder{
Id: uid.String(),
Name: p.Name,
Manufacturer: handlers.Manufacturer{Id: p.ManufacturerID.String(), Name: p.ManufacturerName, Url: p.ManufacturerUrl.String},
},
}
response.Status = http.StatusText(http.StatusOK)
return c.JSON(http.StatusOK, response)
}
powders, err := db.Powder.GetPowders(context.Background())
if err != nil {
return err
}
response := handlers.Response[[]handlers.Powder]{
Payload: make([]handlers.Powder, 0),
}
for _, p := range powders {
response.Payload = append(response.Payload, handlers.Powder{
Id: p.ID.String(),
Name: p.Name,
Manufacturer: handlers.Manufacturer{
Id: p.ManufacturerID.String(),
Name: p.ManufacturerName,
Url: p.ManufacturerUrl.String,
},
})
}
response.Status = http.StatusText(http.StatusOK)
return c.JSON(200, response)
}

View File

@@ -0,0 +1,226 @@
package primers
import (
"context"
"encoding/json"
"git.s.int/reloading-manager/backend/database"
"git.s.int/reloading-manager/backend/handlers"
"git.s.int/reloading-manager/backend/models/primers"
"github.com/google/uuid"
"github.com/labstack/echo/v4"
"net/http"
)
type PrimerResponse struct {
ID string `json:"id"`
Name string `json:"name"`
Manufacturer handlers.Manufacturer `json:"manufacturer"`
}
func Delete(c echo.Context) error {
db := c.(*database.CustomContext).Db
defer db.Db.Close(context.Background())
id := c.Param("id")
uid, err := handlers.ParseUuid(id)
if err != nil {
return handlers.BadRequest(c, "Invalid UUID.")
}
err = db.Primer.DeletePrimer(context.Background(), *uid)
if err != nil {
return err
}
return c.JSON(http.StatusNoContent, handlers.Response[string]{})
}
func Post(c echo.Context) error {
db := c.(*database.CustomContext).Db
defer db.Db.Close(context.Background())
if c.Param("id") != "" {
id := c.Param("id")
uid := handlers.ParseUuidOrBadRequest(c, id)
if uid == nil {
return nil
}
p, err := db.Primer.GetPrimerById(context.Background(), *uid)
if err != nil {
return handlers.NotFound(c, "Primer not found.")
}
if c.FormValue("name") != "" {
p.Name = c.FormValue("name")
}
if c.FormValue("manufacturer_id") != "" {
mid := handlers.ParseUuidOrBadRequest(c, c.FormValue("manufacturer_id"))
if mid == nil {
return nil
}
p.ManufacturerID = *mid
}
if c.FormValue("meta") != "" {
p.Meta = json.RawMessage(c.Param("meta"))
}
file, _ := c.FormFile("photo")
if file != nil {
photo, err := handlers.ReadFile(c, "photo")
if err != nil {
return err
}
p.Photo = photo
}
err = db.Primer.UpdatePrimer(context.Background(), primers.UpdatePrimerParams{
ID: p.ID,
Name: p.Name,
ManufacturerID: p.ManufacturerID,
Meta: p.Meta,
Photo: p.Photo,
})
if err != nil {
return err
}
return c.JSON(http.StatusOK, handlers.Response[string]{Payload: p.ID.String(), Status: http.StatusText(http.StatusOK)})
}
buf, err := handlers.ReadFile(c, "photo")
if err != nil {
return err
}
name := c.FormValue("name")
manufacturerId := c.FormValue("manufacturer_id")
metaString := c.FormValue("meta")
if name == "" {
return handlers.BadRequest(c, "Name is required.")
}
if manufacturerId == "" {
return handlers.BadRequest(c, "Manufacturer ID is required.")
}
if metaString == "" {
metaString = "{}"
}
var meta json.RawMessage = []byte(metaString)
newUuid := uuid.New().String()
uid, _ := handlers.ParseUuid(newUuid)
mid := handlers.ParseUuidOrBadRequest(c, manufacturerId)
if mid == nil {
return nil
}
err = db.Primer.InsertPrimer(context.Background(), primers.InsertPrimerParams{
ID: *uid,
Name: name,
ManufacturerID: *mid,
Meta: meta,
Photo: buf,
})
if err != nil {
return err
}
return c.JSON(http.StatusCreated, handlers.Response[struct {
Id string `json:"id"`
}]{
Status: http.StatusText(http.StatusCreated),
Payload: struct {
Id string `json:"id"`
}{Id: newUuid},
})
}
func Photo(c echo.Context) error {
db := c.(*database.CustomContext).Db
defer db.Db.Close(context.Background())
id := c.Param("id")
uid := handlers.ParseUuidOrBadRequest(c, id)
if uid == nil {
return nil
}
byId, err := db.Primer.GetPrimerById(context.Background(), *uid)
if err != nil {
return echo.NewHTTPError(http.StatusNotFound, "Not found")
}
mime := http.DetectContentType(byId.Photo)
c.Response().Header().Set("Content-Type", mime)
c.Response().Header().Set("Cache-Control", "no-cache, no-store, must-revalidate")
c.Response().Header().Set("Pragma", "no-cache")
c.Response().Header().Set("Expires", "0")
_, err = c.Response().Write(byId.Photo)
return err
}
func Get(c echo.Context) error {
db := c.(*database.CustomContext).Db
defer db.Db.Close(context.Background())
if c.Param("id") != "" {
id := c.Param("id")
uid := handlers.ParseUuidOrBadRequest(c, id)
if uid == nil {
return nil
}
row, err := db.Primer.GetPrimerById(context.Background(), *uid)
if err != nil {
return err
}
return c.JSON(http.StatusOK, handlers.Response[PrimerResponse]{
Status: http.StatusText(http.StatusOK),
Payload: PrimerResponse{
ID: row.ID.String(),
Name: row.Name,
Manufacturer: handlers.Manufacturer{
Id: row.ManufacturerID.String(),
Name: row.ManufacturerName,
Url: row.ManufacturerUrl.String,
},
},
})
}
rows, err := db.Primer.GetPrimers(context.Background())
if err != nil {
return err
}
response := handlers.Response[[]PrimerResponse]{
Status: "OK",
Payload: make([]PrimerResponse, 0),
}
for _, row := range rows {
response.Payload = append(response.Payload, PrimerResponse{
ID: row.ID.String(),
Name: row.Name,
Manufacturer: handlers.Manufacturer{
Id: row.ManufacturerID.String(),
Name: row.ManufacturerName,
Url: row.ManufacturerUrl.String,
},
})
}
return c.JSON(http.StatusOK, response)
}

View File

@@ -0,0 +1,42 @@
package handlers
import (
"github.com/labstack/echo/v4"
"net/http"
)
const DateFormat = "2006-01-02 15:04:05"
type Response[T any] struct {
Status string `json:"status"`
Message string `json:"message,omitempty"`
Payload T `json:"payload"`
}
func BadRequest(c echo.Context, message string) error {
return c.JSON(http.StatusBadRequest, Response[string]{
Status: http.StatusText(http.StatusBadRequest),
Message: message,
})
}
func NotFound(c echo.Context, message string) error {
return c.JSON(http.StatusNotFound, Response[string]{
Status: http.StatusText(http.StatusNotFound),
Message: message,
})
}
type Manufacturer struct {
Id string `json:"id"`
Name string `json:"name"`
Url string `json:"url"`
}
type Powder struct {
Id string `json:"id"`
Name string `json:"name"`
Meta string `json:"meta"`
Photo string `json:"photo,omitempty"`
Manufacturer Manufacturer `json:"manufacturer"`
}

View File

@@ -0,0 +1,38 @@
package handlers
import (
"github.com/labstack/echo/v4"
"testing"
)
type TestContext struct {
echo.Context
t *testing.T
}
func (t TestContext) JSON(code int, i interface{}) error {
if code != 400 {
t.t.Fatal("expected 400")
}
switch i.(type) {
case Response[string]:
break
default:
t.t.Fatal("expected response")
}
return nil
}
func TestBadRequest(t *testing.T) {
context := TestContext{
t: t,
}
err := BadRequest(context, "Something is wrong")
if err != nil {
t.Errorf("Should not have returned an error")
}
}

45
backend/handlers/uuid.go Normal file
View File

@@ -0,0 +1,45 @@
package handlers
import (
"github.com/google/uuid"
"github.com/jackc/pgx/v5/pgtype"
"github.com/labstack/echo/v4"
)
func ParseUuidOrEmpty(s string) *pgtype.UUID {
ParsedUuid, err := uuid.Parse(s)
if err != nil {
return &pgtype.UUID{
Valid: false,
}
}
return &pgtype.UUID{
Bytes: ParsedUuid,
Valid: true,
}
}
func ParseUuid(s string) (*pgtype.UUID, error) {
uid, err := uuid.Parse(s)
if err != nil {
return nil, err
}
return &pgtype.UUID{
Bytes: uid,
Valid: true,
}, nil
}
func ParseUuidOrBadRequest(c echo.Context, s string) *pgtype.UUID {
uid, err := ParseUuid(s)
if err != nil {
_ = BadRequest(c, "Invalid UUID.")
return nil
}
return uid
}

114
backend/main.go Normal file
View File

@@ -0,0 +1,114 @@
package main
import (
"context"
"fmt"
"git.s.int/packages/go/utilities/Env"
"git.s.int/reloading-manager/backend/database"
"git.s.int/reloading-manager/backend/handlers/bullets"
"git.s.int/reloading-manager/backend/handlers/cartridge"
"git.s.int/reloading-manager/backend/handlers/loads"
"git.s.int/reloading-manager/backend/handlers/manufacturer"
"git.s.int/reloading-manager/backend/handlers/powder"
"git.s.int/reloading-manager/backend/handlers/primers"
"github.com/go-playground/validator"
"github.com/labstack/echo/v4"
"github.com/labstack/echo/v4/middleware"
"github.com/labstack/gommon/log"
"net/http"
)
const (
Port Env.EnvironmentVariable = "PORT"
)
type (
CustomValidator struct {
validator *validator.Validate
}
)
func (cv *CustomValidator) Validate(i interface{}) error {
if err := cv.validator.Struct(i); err != nil {
return echo.NewHTTPError(http.StatusBadRequest, err.Error())
}
return nil
}
func main() {
e := echo.New()
e.Validator = &CustomValidator{validator: validator.New()}
e.HideBanner = true
e.HidePort = true
e.Logger.SetLevel(log.DEBUG)
e.Use(database.CreateDatabaseMiddleware())
e.Use(middleware.Recover())
e.Use(middleware.Logger())
e.Use(middleware.CORSWithConfig(middleware.CORSConfig{
AllowOrigins: []string{"http://localhost:5173", "http://127.0.0.1:5173"},
AllowMethods: []string{"GET", "POST", "PUT", "PATCH", "DELETE"},
}))
migrate(e)
// Bullets
e.GET("/bullet", bullets.Get)
e.GET("/bullet/:id", bullets.Get)
e.GET("/bullet/:id/photo", bullets.Photo)
e.POST("/bullet", bullets.Post)
e.POST("/bullet/:id", bullets.Put)
e.DELETE("/bullet/:id", bullets.Delete)
// Manufacturers
e.GET("/manufacturer", manufacturer.Get)
e.GET("/manufacturer/:id", manufacturer.Get)
e.POST("/manufacturer", manufacturer.Post)
e.POST("/manufacturer/:id", manufacturer.Post)
e.DELETE("/manufacturer/:id", manufacturer.Delete)
// Powders
e.GET("/powder", powder.Get)
e.GET("/powder/:id", powder.Get)
e.GET("/powder/:id/photo", powder.Photo)
e.POST("/powder", powder.Post)
e.POST("/powder/:id", powder.Post)
e.DELETE("/powder/:id", powder.Delete)
// Primers
e.GET("/primer", primers.Get)
e.GET("/primer/:id", primers.Get)
e.GET("/primer/:id/photo", primers.Photo)
e.POST("/primer", primers.Post)
e.POST("/primer/:id", primers.Post)
e.DELETE("/primer/:id", primers.Delete)
// cartridge
e.GET("/cartridge", cartridge.Get)
e.POST("/cartridge", cartridge.Post)
e.DELETE("/cartridge/:id", cartridge.Delete)
// loads
e.GET("/load", loads.Get)
e.POST("/load", loads.Post)
addr := fmt.Sprintf("0.0.0.0:%s", Port.GetEnvString("8080"))
e.Logger.Info("Starting Server...")
e.Logger.Infof("Listening on %v", addr)
e.Logger.Fatal(e.Start(addr))
}
func migrate(e *echo.Echo) {
e.Logger.Info("Starting migrations...")
db := database.GetNewDatabase()
defer db.Db.Close(context.Background())
db.Migrate()
e.Logger.Info("Done!")
}

View File

@@ -0,0 +1,2 @@
drop table if exists bullets;
drop table if exists manufacturers;

View File

@@ -0,0 +1,42 @@
create table manufacturers
(
id uuid primary key default gen_random_uuid(),
name varchar(255) not null,
url varchar(255),
created_at timestamp default NOW() not null
);
insert into manufacturers (name, url)
values ('Hornady', 'https://www.hornady.com/'),
('CCI', 'https://www.cci-ammunition.com/'),
('IMR Powders', 'https://shop.hodgdon.com/imr/'),
('Accurate Powders', 'https://hodgdonpowderco.com/accurate/'),
('Federal', 'https://www.federalpremium.com/'),
('Remington', 'https://www.remington.com/'),
('Winchester', 'https://www.winchester.com/'),
('Speer', 'https://www.speer.com/'),
('Nosler', 'https://www.nosler.com/'),
('Sierra', 'https://www.sierrabullets.com/'),
('Barnes', 'https://www.barnesbullets.com/'),
('Berger', 'https://www.bergerbullets.com/'),
('Lapua', 'https://www.lapua.com/'),
('Norma', 'https://www.norma-ammunition.com/'),
('Berrys Bullets', 'https://www.berrysmfg.com/'),
('Starline Brass', 'https://www.starlinebrass.com/'),
('Swift', 'https://www.swiftbullets.com/');
create table bullets
(
id uuid primary key default gen_random_uuid(),
name varchar(255) not null,
weight int not null,
diameter int not null,
meta json,
photo bytea,
manufacturer_id uuid not null,
created_at timestamp default NOW() not null
);
alter table bullets
add constraint bullets_manufacturers_id_fk
foreign key (manufacturer_id) references manufacturers (id);

View File

@@ -0,0 +1 @@
drop table if exists powders;

View File

@@ -0,0 +1,11 @@
create table powders
(
id uuid primary key default gen_random_uuid(),
name varchar(255) not null,
meta json,
photo bytea,
manufacturer_id uuid not null,
created_at timestamp default NOW() not null,
constraint powders_manufacturers_id_fk
foreign key (manufacturer_id) references manufacturers (id)
);

View File

@@ -0,0 +1,11 @@
create table primers
(
id uuid primary key default gen_random_uuid(),
name varchar(255) not null,
meta json,
photo bytea,
manufacturer_id uuid not null,
created_at timestamp default NOW() not null,
constraint primers_manufacturers_id_fk
foreign key (manufacturer_id) references manufacturers (id)
);

View File

@@ -0,0 +1,2 @@
drop table if exists loads;
drop table if exists cartridges;

View File

@@ -0,0 +1,32 @@
create table cartridges
(
id uuid primary key default gen_random_uuid(),
name varchar(255) not null,
created_at timestamp default current_timestamp not null,
meta json not null,
constraint cartridges_name_uindex
unique (name)
);
create table loads
(
id uuid primary key default gen_random_uuid(),
cartridge_id uuid not null,
col float4 not null,
powder_id uuid not null,
powder_gr float4 not null,
primer_id uuid not null,
bullet_id uuid not null,
photo bytea not null,
created_at timestamp default current_timestamp not null,
meta json not null,
constraint loads_bullets_id_fk
foreign key (bullet_id) references bullets (id),
constraint loads_powders_id_fk
foreign key (powder_id) references powders (id),
constraint loads_primers_id_fk
foreign key (primer_id) references primers (id),
constraint loads_cartridges_id_fk
foreign key (cartridge_id) references cartridges (id)
);

View File

@@ -0,0 +1,20 @@
create table bullets
(
id uuid primary key,
name varchar(255) not null,
weight int not null,
diameter int not null,
meta json,
photo bytea,
manufacturer_id uuid not null,
created_at timestamp default NOW() not null
);
create table manufacturers
(
id uuid primary key ,
name varchar(255) not null,
url varchar(255),
created_at timestamp default NOW() not null
);

View File

@@ -0,0 +1,63 @@
-- name: GetBullets :many
select bullets.id as id,
bullets.name as name,
weight,
diameter,
bullets.created_at,
meta,
m.id as manufacturer_id,
m.name as manufacturer_name,
m.url as manufacturer_url
from bullets
join manufacturers m on m.id = bullets.manufacturer_id
order by manufacturer_name, bullets.name desc;
-- name: GetBulletById :one
select bullets.id as id,
bullets.name,
bullets.diameter,
bullets.weight,
bullets.meta,
bullets.photo,
bullets.created_at,
m.id as manufactuerer_id,
m.name as manufacutuer_name,
m.url as manufacturer_url
from bullets
join manufacturers m on m.id = bullets.manufacturer_id
where bullets.id = $1;
-- name: ForPage :many
select bullets.id as id,
bullets.name as name,
weight,
diameter,
bullets.created_at,
meta,
m.id as manufacturer_id,
m.name as manufacturer_name,
m.url as manufacturer_url
from bullets
join manufacturers m on m.id = bullets.manufacturer_id
order by manufacturer_name, bullets.name desc
limit $1 offset $2;
-- name: DeleteBullet :exec
DELETE
from bullets
where id = $1;
-- name: AddBullet :one
insert into bullets (name, weight, diameter, photo, meta, manufacturer_id)
values ($1, $2, $3, $4, $5, $6)
returning id;
-- name: UpdateBullet :exec
UPDATE bullets
set name=$1,
weight=$2,
diameter=$3,
photo=$4,
meta=$5,
manufacturer_id=$6
where id = $7;

View File

@@ -0,0 +1,253 @@
// Code generated by sqlc. DO NOT EDIT.
// versions:
// sqlc v1.27.0
// source: bullets.sql
package bullets
import (
"context"
"github.com/jackc/pgx/v5/pgtype"
)
const addBullet = `-- name: AddBullet :one
insert into bullets (name, weight, diameter, photo, meta, manufacturer_id)
values ($1, $2, $3, $4, $5, $6)
returning id
`
type AddBulletParams struct {
Name string `json:"name"`
Weight int32 `json:"weight"`
Diameter int32 `json:"diameter"`
Photo []byte `json:"photo"`
Meta []byte `json:"meta"`
ManufacturerID pgtype.UUID `json:"manufacturer_id"`
}
func (q *Queries) AddBullet(ctx context.Context, arg AddBulletParams) (pgtype.UUID, error) {
row := q.db.QueryRow(ctx, addBullet,
arg.Name,
arg.Weight,
arg.Diameter,
arg.Photo,
arg.Meta,
arg.ManufacturerID,
)
var id pgtype.UUID
err := row.Scan(&id)
return id, err
}
const deleteBullet = `-- name: DeleteBullet :exec
DELETE
from bullets
where id = $1
`
func (q *Queries) DeleteBullet(ctx context.Context, id pgtype.UUID) error {
_, err := q.db.Exec(ctx, deleteBullet, id)
return err
}
const forPage = `-- name: ForPage :many
select bullets.id as id,
bullets.name as name,
weight,
diameter,
bullets.created_at,
meta,
m.id as manufacturer_id,
m.name as manufacturer_name,
m.url as manufacturer_url
from bullets
join manufacturers m on m.id = bullets.manufacturer_id
order by manufacturer_name, bullets.name desc
limit $1 offset $2
`
type ForPageParams struct {
Limit int32 `json:"limit"`
Offset int32 `json:"offset"`
}
type ForPageRow struct {
ID pgtype.UUID `json:"id"`
Name string `json:"name"`
Weight int32 `json:"weight"`
Diameter int32 `json:"diameter"`
CreatedAt pgtype.Timestamp `json:"created_at"`
Meta []byte `json:"meta"`
ManufacturerID pgtype.UUID `json:"manufacturer_id"`
ManufacturerName string `json:"manufacturer_name"`
ManufacturerUrl pgtype.Text `json:"manufacturer_url"`
}
func (q *Queries) ForPage(ctx context.Context, arg ForPageParams) ([]ForPageRow, error) {
rows, err := q.db.Query(ctx, forPage, arg.Limit, arg.Offset)
if err != nil {
return nil, err
}
defer rows.Close()
var items []ForPageRow
for rows.Next() {
var i ForPageRow
if err := rows.Scan(
&i.ID,
&i.Name,
&i.Weight,
&i.Diameter,
&i.CreatedAt,
&i.Meta,
&i.ManufacturerID,
&i.ManufacturerName,
&i.ManufacturerUrl,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const getBulletById = `-- name: GetBulletById :one
select bullets.id as id,
bullets.name,
bullets.diameter,
bullets.weight,
bullets.meta,
bullets.photo,
bullets.created_at,
m.id as manufactuerer_id,
m.name as manufacutuer_name,
m.url as manufacturer_url
from bullets
join manufacturers m on m.id = bullets.manufacturer_id
where bullets.id = $1
`
type GetBulletByIdRow struct {
ID pgtype.UUID `json:"id"`
Name string `json:"name"`
Diameter int32 `json:"diameter"`
Weight int32 `json:"weight"`
Meta []byte `json:"meta"`
Photo []byte `json:"photo"`
CreatedAt pgtype.Timestamp `json:"created_at"`
ManufactuererID pgtype.UUID `json:"manufactuerer_id"`
ManufacutuerName string `json:"manufacutuer_name"`
ManufacturerUrl pgtype.Text `json:"manufacturer_url"`
}
func (q *Queries) GetBulletById(ctx context.Context, id pgtype.UUID) (GetBulletByIdRow, error) {
row := q.db.QueryRow(ctx, getBulletById, id)
var i GetBulletByIdRow
err := row.Scan(
&i.ID,
&i.Name,
&i.Diameter,
&i.Weight,
&i.Meta,
&i.Photo,
&i.CreatedAt,
&i.ManufactuererID,
&i.ManufacutuerName,
&i.ManufacturerUrl,
)
return i, err
}
const getBullets = `-- name: GetBullets :many
select bullets.id as id,
bullets.name as name,
weight,
diameter,
bullets.created_at,
meta,
m.id as manufacturer_id,
m.name as manufacturer_name,
m.url as manufacturer_url
from bullets
join manufacturers m on m.id = bullets.manufacturer_id
order by manufacturer_name, bullets.name desc
`
type GetBulletsRow struct {
ID pgtype.UUID `json:"id"`
Name string `json:"name"`
Weight int32 `json:"weight"`
Diameter int32 `json:"diameter"`
CreatedAt pgtype.Timestamp `json:"created_at"`
Meta []byte `json:"meta"`
ManufacturerID pgtype.UUID `json:"manufacturer_id"`
ManufacturerName string `json:"manufacturer_name"`
ManufacturerUrl pgtype.Text `json:"manufacturer_url"`
}
func (q *Queries) GetBullets(ctx context.Context) ([]GetBulletsRow, error) {
rows, err := q.db.Query(ctx, getBullets)
if err != nil {
return nil, err
}
defer rows.Close()
var items []GetBulletsRow
for rows.Next() {
var i GetBulletsRow
if err := rows.Scan(
&i.ID,
&i.Name,
&i.Weight,
&i.Diameter,
&i.CreatedAt,
&i.Meta,
&i.ManufacturerID,
&i.ManufacturerName,
&i.ManufacturerUrl,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const updateBullet = `-- name: UpdateBullet :exec
UPDATE bullets
set name=$1,
weight=$2,
diameter=$3,
photo=$4,
meta=$5,
manufacturer_id=$6
where id = $7
`
type UpdateBulletParams struct {
Name string `json:"name"`
Weight int32 `json:"weight"`
Diameter int32 `json:"diameter"`
Photo []byte `json:"photo"`
Meta []byte `json:"meta"`
ManufacturerID pgtype.UUID `json:"manufacturer_id"`
ID pgtype.UUID `json:"id"`
}
func (q *Queries) UpdateBullet(ctx context.Context, arg UpdateBulletParams) error {
_, err := q.db.Exec(ctx, updateBullet,
arg.Name,
arg.Weight,
arg.Diameter,
arg.Photo,
arg.Meta,
arg.ManufacturerID,
arg.ID,
)
return err
}

View File

@@ -0,0 +1,32 @@
// Code generated by sqlc. DO NOT EDIT.
// versions:
// sqlc v1.27.0
package bullets
import (
"context"
"github.com/jackc/pgx/v5"
"github.com/jackc/pgx/v5/pgconn"
)
type DBTX interface {
Exec(context.Context, string, ...interface{}) (pgconn.CommandTag, error)
Query(context.Context, string, ...interface{}) (pgx.Rows, error)
QueryRow(context.Context, string, ...interface{}) pgx.Row
}
func New(db DBTX) *Queries {
return &Queries{db: db}
}
type Queries struct {
db DBTX
}
func (q *Queries) WithTx(tx pgx.Tx) *Queries {
return &Queries{
db: tx,
}
}

View File

@@ -0,0 +1,27 @@
// Code generated by sqlc. DO NOT EDIT.
// versions:
// sqlc v1.27.0
package bullets
import (
"github.com/jackc/pgx/v5/pgtype"
)
type Bullet struct {
ID pgtype.UUID `json:"id"`
Name string `json:"name"`
Weight int32 `json:"weight"`
Diameter int32 `json:"diameter"`
Meta []byte `json:"meta"`
Photo []byte `json:"photo"`
ManufacturerID pgtype.UUID `json:"manufacturer_id"`
CreatedAt pgtype.Timestamp `json:"created_at"`
}
type Manufacturer struct {
ID pgtype.UUID `json:"id"`
Name string `json:"name"`
Url pgtype.Text `json:"url"`
CreatedAt pgtype.Timestamp `json:"created_at"`
}

View File

@@ -0,0 +1,73 @@
create table cartridges
(
id uuid primary key,
name varchar(255) not null,
created_at timestamp default current_timestamp not null,
meta json not null
);
create table loads
(
id uuid primary key,
cartridge_id uuid not null,
col float4 not null,
powder_id uuid not null,
powder_gr float4 not null,
primer_id uuid not null,
bullet_id uuid not null,
photo bytea not null,
created_at timestamp default current_timestamp not null,
meta json not null,
constraint loads_bullets_id_fk
foreign key (bullet_id) references bullets (id),
constraint loads_powders_id_fk
foreign key (powder_id) references powders (id),
constraint loads_primers_id_fk
foreign key (primer_id) references primers (id),
constraint loads_cartridges_id_fk
foreign key (cartridge_id) references cartridges (id)
);
create table bullets
(
id uuid primary key,
name varchar(255) not null,
weight int not null,
diameter int not null,
meta json,
photo bytea,
manufacturer_id uuid not null,
created_at timestamp default NOW() not null
);
create table manufacturers
(
id uuid primary key,
name varchar(255) not null,
url varchar(255),
created_at timestamp default NOW() not null
);
create table powders
(
id uuid primary key,
name varchar(255) not null,
meta json,
photo bytea,
manufacturer_id uuid not null,
created_at timestamp default NOW() not null,
constraint powders_manufacturers_id_fk
foreign key (manufacturer_id) references manufacturers (id)
);
create table primers
(
id uuid primary key,
name varchar(255) not null,
meta json,
photo bytea,
manufacturer_id uuid not null,
created_at timestamp default NOW() not null,
constraint primers_manufacturers_id_fk
foreign key (manufacturer_id) references manufacturers (id)
);

100
backend/models/loads.sql Normal file
View File

@@ -0,0 +1,100 @@
-- name: GetCartridgeById :one
select c.id as id, c.name, c.meta
from cartridges c
where id = $1;
-- name: GetCartridges :many
select c.id as id, c.name, c.meta
from cartridges c
order by c.name;
-- name: CreateCartridge :one
insert into cartridges (name, meta)
values ($1, $2)
returning id;
-- name: DeleteCartridge :exec
delete
from cartridges
where id = $1;
-- name: CreateLoad :one
insert into loads (cartridge_id, col, powder_id, powder_gr, primer_id, bullet_id, photo, meta)
values ($1, $2, $3, $4, $5, $6, $7, $8)
returning id;
-- name: GetLoadById :one
select l.id as id,
c.id as cartridge_id,
c.name as cartridge_name,
c.meta as cartridge_meta,
l.col,
p.id as powder_id,
p.name as powder_name,
p.meta as powder_meta,
l.powder_gr,
pr.id as primer_id,
pr.name as primer_name,
pr.meta as primer_meta
from public.loads l
join cartridges c on l.cartridge_id = c.id
join bullets b on l.bullet_id = b.id
join powders p on l.powder_id = p.id
join primers pr on l.primer_id = pr.id
where l.id = $1;
-- name: TotalLoads :one
select count(*)
from loads;
-- name: GetLoads :many
select l.id as id,
l.col,
l.powder_gr,
c.id as cartridge_id,
c.name as cartridge_name,
c.meta as cartridge_meta,
p.id as powder_id,
p.name as powder_name,
p.meta as powder_meta,
p_m.name as powder_manufacturer_name,
p_m.url as powder_manufacturer_url,
pr.id as primer_id,
pr.name as primer_name,
pr.meta as primer_meta,
pr_m.name as primer_manufacturer_name,
pr_m.url as primer_manufacturer_url,
b.id as bullet_id,
b.name as bullet_name,
b.meta as bullet_meta,
b.weight as bullet_weight,
b.diameter as bullet_diameter,
b_m.name as bullet_manufacturer_name,
b_m.url as bullet_manufacturer_url
from public.loads l
join cartridges c on l.cartridge_id = c.id
join bullets b on l.bullet_id = b.id
join manufacturers b_m on b.manufacturer_id = b_m.id
join powders p on l.powder_id = p.id
join manufacturers p_m on p.manufacturer_id = p_m.id
join primers pr on l.primer_id = pr.id
join manufacturers pr_m on pr.manufacturer_id = pr_m.id
where 1 = 1
-- Loose Search By Name
AND (CASE WHEN @search_cartridge::bool THEN lower(c.name) like lower(@cartridge) ELSE TRUE END)
AND (CASE WHEN @search_bullet::bool THEN lower(b.name) like lower(@bullet) ELSE TRUE END)
AND (CASE WHEN @search_bullet_manufacturer::bool THEN lower(b_m.name) like lower(@bullet_manufacturer) ELSE TRUE END)
AND (CASE WHEN @search_primer::bool THEN lower(pr.name) like lower(@primer) ELSE TRUE END)
AND (CASE WHEN @search_primer_manufacturer::bool THEN lower(pr_m.name) like lower(@prime_manufacturer) ELSE TRUE END)
AND (CASE WHEN @search_powder::bool THEN lower(p.name) like lower(@powder) ELSE TRUE END)
AND (CASE WHEN @search_powder_manufacturer::bool THEN lower(p_m.name) like lower(@powder_manufacturer) ELSE TRUE END)
-- Exact Search By ID
AND (CASE WHEN @search_cartridge_id::bool THEN c.id = @cartridge_id::uuid ELSE TRUE END)
AND (CASE WHEN @search_bullet_id::bool THEN b.id = @bullet_id::uuid ELSE TRUE END)
AND (CASE WHEN @search_primer_id::bool THEN pr.id = @primer_id::uuid ELSE TRUE END)
AND (CASE WHEN @search_powder_id::bool THEN p.id = @powder_id::uuid ELSE TRUE END)
order by @order_by
limit $1 offset $2;

View File

@@ -0,0 +1,32 @@
// Code generated by sqlc. DO NOT EDIT.
// versions:
// sqlc v1.27.0
package loads
import (
"context"
"github.com/jackc/pgx/v5"
"github.com/jackc/pgx/v5/pgconn"
)
type DBTX interface {
Exec(context.Context, string, ...interface{}) (pgconn.CommandTag, error)
Query(context.Context, string, ...interface{}) (pgx.Rows, error)
QueryRow(context.Context, string, ...interface{}) pgx.Row
}
func New(db DBTX) *Queries {
return &Queries{db: db}
}
type Queries struct {
db DBTX
}
func (q *Queries) WithTx(tx pgx.Tx) *Queries {
return &Queries{
db: tx,
}
}

View File

@@ -0,0 +1,370 @@
// Code generated by sqlc. DO NOT EDIT.
// versions:
// sqlc v1.27.0
// source: loads.sql
package loads
import (
"context"
"github.com/jackc/pgx/v5/pgtype"
)
const createCartridge = `-- name: CreateCartridge :one
insert into cartridges (name, meta)
values ($1, $2)
returning id
`
type CreateCartridgeParams struct {
Name string `json:"name"`
Meta []byte `json:"meta"`
}
func (q *Queries) CreateCartridge(ctx context.Context, arg CreateCartridgeParams) (pgtype.UUID, error) {
row := q.db.QueryRow(ctx, createCartridge, arg.Name, arg.Meta)
var id pgtype.UUID
err := row.Scan(&id)
return id, err
}
const createLoad = `-- name: CreateLoad :one
insert into loads (cartridge_id, col, powder_id, powder_gr, primer_id, bullet_id, photo, meta)
values ($1, $2, $3, $4, $5, $6, $7, $8)
returning id
`
type CreateLoadParams struct {
CartridgeID pgtype.UUID `json:"cartridge_id"`
Col float32 `json:"col"`
PowderID pgtype.UUID `json:"powder_id"`
PowderGr float32 `json:"powder_gr"`
PrimerID pgtype.UUID `json:"primer_id"`
BulletID pgtype.UUID `json:"bullet_id"`
Photo []byte `json:"photo"`
Meta []byte `json:"meta"`
}
func (q *Queries) CreateLoad(ctx context.Context, arg CreateLoadParams) (pgtype.UUID, error) {
row := q.db.QueryRow(ctx, createLoad,
arg.CartridgeID,
arg.Col,
arg.PowderID,
arg.PowderGr,
arg.PrimerID,
arg.BulletID,
arg.Photo,
arg.Meta,
)
var id pgtype.UUID
err := row.Scan(&id)
return id, err
}
const deleteCartridge = `-- name: DeleteCartridge :exec
delete
from cartridges
where id = $1
`
func (q *Queries) DeleteCartridge(ctx context.Context, id pgtype.UUID) error {
_, err := q.db.Exec(ctx, deleteCartridge, id)
return err
}
const getCartridgeById = `-- name: GetCartridgeById :one
select c.id as id, c.name, c.meta
from cartridges c
where id = $1
`
type GetCartridgeByIdRow struct {
ID pgtype.UUID `json:"id"`
Name string `json:"name"`
Meta []byte `json:"meta"`
}
func (q *Queries) GetCartridgeById(ctx context.Context, id pgtype.UUID) (GetCartridgeByIdRow, error) {
row := q.db.QueryRow(ctx, getCartridgeById, id)
var i GetCartridgeByIdRow
err := row.Scan(&i.ID, &i.Name, &i.Meta)
return i, err
}
const getCartridges = `-- name: GetCartridges :many
select c.id as id, c.name, c.meta
from cartridges c
order by c.name
`
type GetCartridgesRow struct {
ID pgtype.UUID `json:"id"`
Name string `json:"name"`
Meta []byte `json:"meta"`
}
func (q *Queries) GetCartridges(ctx context.Context) ([]GetCartridgesRow, error) {
rows, err := q.db.Query(ctx, getCartridges)
if err != nil {
return nil, err
}
defer rows.Close()
var items []GetCartridgesRow
for rows.Next() {
var i GetCartridgesRow
if err := rows.Scan(&i.ID, &i.Name, &i.Meta); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const getLoadById = `-- name: GetLoadById :one
select l.id as id,
c.id as cartridge_id,
c.name as cartridge_name,
c.meta as cartridge_meta,
l.col,
p.id as powder_id,
p.name as powder_name,
p.meta as powder_meta,
l.powder_gr,
pr.id as primer_id,
pr.name as primer_name,
pr.meta as primer_meta
from public.loads l
join cartridges c on l.cartridge_id = c.id
join bullets b on l.bullet_id = b.id
join powders p on l.powder_id = p.id
join primers pr on l.primer_id = pr.id
where l.id = $1
`
type GetLoadByIdRow struct {
ID pgtype.UUID `json:"id"`
CartridgeID pgtype.UUID `json:"cartridge_id"`
CartridgeName string `json:"cartridge_name"`
CartridgeMeta []byte `json:"cartridge_meta"`
Col float32 `json:"col"`
PowderID pgtype.UUID `json:"powder_id"`
PowderName string `json:"powder_name"`
PowderMeta []byte `json:"powder_meta"`
PowderGr float32 `json:"powder_gr"`
PrimerID pgtype.UUID `json:"primer_id"`
PrimerName string `json:"primer_name"`
PrimerMeta []byte `json:"primer_meta"`
}
func (q *Queries) GetLoadById(ctx context.Context, id pgtype.UUID) (GetLoadByIdRow, error) {
row := q.db.QueryRow(ctx, getLoadById, id)
var i GetLoadByIdRow
err := row.Scan(
&i.ID,
&i.CartridgeID,
&i.CartridgeName,
&i.CartridgeMeta,
&i.Col,
&i.PowderID,
&i.PowderName,
&i.PowderMeta,
&i.PowderGr,
&i.PrimerID,
&i.PrimerName,
&i.PrimerMeta,
)
return i, err
}
const getLoads = `-- name: GetLoads :many
select l.id as id,
l.col,
l.powder_gr,
c.id as cartridge_id,
c.name as cartridge_name,
c.meta as cartridge_meta,
p.id as powder_id,
p.name as powder_name,
p.meta as powder_meta,
p_m.name as powder_manufacturer_name,
p_m.url as powder_manufacturer_url,
pr.id as primer_id,
pr.name as primer_name,
pr.meta as primer_meta,
pr_m.name as primer_manufacturer_name,
pr_m.url as primer_manufacturer_url,
b.id as bullet_id,
b.name as bullet_name,
b.meta as bullet_meta,
b.weight as bullet_weight,
b.diameter as bullet_diameter,
b_m.name as bullet_manufacturer_name,
b_m.url as bullet_manufacturer_url
from public.loads l
join cartridges c on l.cartridge_id = c.id
join bullets b on l.bullet_id = b.id
join manufacturers b_m on b.manufacturer_id = b_m.id
join powders p on l.powder_id = p.id
join manufacturers p_m on p.manufacturer_id = p_m.id
join primers pr on l.primer_id = pr.id
join manufacturers pr_m on pr.manufacturer_id = pr_m.id
where 1 = 1
-- Loose Search By Name
AND (CASE WHEN $3::bool THEN lower(c.name) like lower($4) ELSE TRUE END)
AND (CASE WHEN $5::bool THEN lower(b.name) like lower($6) ELSE TRUE END)
AND (CASE WHEN $7::bool THEN lower(b_m.name) like lower($8) ELSE TRUE END)
AND (CASE WHEN $9::bool THEN lower(pr.name) like lower($10) ELSE TRUE END)
AND (CASE WHEN $11::bool THEN lower(pr_m.name) like lower($12) ELSE TRUE END)
AND (CASE WHEN $13::bool THEN lower(p.name) like lower($14) ELSE TRUE END)
AND (CASE WHEN $15::bool THEN lower(p_m.name) like lower($16) ELSE TRUE END)
-- Exact Search By ID
AND (CASE WHEN $17::bool THEN c.id = $18::uuid ELSE TRUE END)
AND (CASE WHEN $19::bool THEN b.id = $20::uuid ELSE TRUE END)
AND (CASE WHEN $21::bool THEN pr.id = $22::uuid ELSE TRUE END)
AND (CASE WHEN $23::bool THEN p.id = $24::uuid ELSE TRUE END)
order by $25
limit $1 offset $2
`
type GetLoadsParams struct {
Limit int32 `json:"limit"`
Offset int32 `json:"offset"`
SearchCartridge bool `json:"search_cartridge"`
Cartridge string `json:"cartridge"`
SearchBullet bool `json:"search_bullet"`
Bullet string `json:"bullet"`
SearchBulletManufacturer bool `json:"search_bullet_manufacturer"`
BulletManufacturer string `json:"bullet_manufacturer"`
SearchPrimer bool `json:"search_primer"`
Primer string `json:"primer"`
SearchPrimerManufacturer bool `json:"search_primer_manufacturer"`
PrimeManufacturer string `json:"prime_manufacturer"`
SearchPowder bool `json:"search_powder"`
Powder string `json:"powder"`
SearchPowderManufacturer bool `json:"search_powder_manufacturer"`
PowderManufacturer string `json:"powder_manufacturer"`
SearchCartridgeID bool `json:"search_cartridge_id"`
CartridgeID pgtype.UUID `json:"cartridge_id"`
SearchBulletID bool `json:"search_bullet_id"`
BulletID pgtype.UUID `json:"bullet_id"`
SearchPrimerID bool `json:"search_primer_id"`
PrimerID pgtype.UUID `json:"primer_id"`
SearchPowderID bool `json:"search_powder_id"`
PowderID pgtype.UUID `json:"powder_id"`
OrderBy interface{} `json:"order_by"`
}
type GetLoadsRow struct {
ID pgtype.UUID `json:"id"`
Col float32 `json:"col"`
PowderGr float32 `json:"powder_gr"`
CartridgeID pgtype.UUID `json:"cartridge_id"`
CartridgeName string `json:"cartridge_name"`
CartridgeMeta []byte `json:"cartridge_meta"`
PowderID pgtype.UUID `json:"powder_id"`
PowderName string `json:"powder_name"`
PowderMeta []byte `json:"powder_meta"`
PowderManufacturerName string `json:"powder_manufacturer_name"`
PowderManufacturerUrl pgtype.Text `json:"powder_manufacturer_url"`
PrimerID pgtype.UUID `json:"primer_id"`
PrimerName string `json:"primer_name"`
PrimerMeta []byte `json:"primer_meta"`
PrimerManufacturerName string `json:"primer_manufacturer_name"`
PrimerManufacturerUrl pgtype.Text `json:"primer_manufacturer_url"`
BulletID pgtype.UUID `json:"bullet_id"`
BulletName string `json:"bullet_name"`
BulletMeta []byte `json:"bullet_meta"`
BulletWeight int32 `json:"bullet_weight"`
BulletDiameter int32 `json:"bullet_diameter"`
BulletManufacturerName string `json:"bullet_manufacturer_name"`
BulletManufacturerUrl pgtype.Text `json:"bullet_manufacturer_url"`
}
func (q *Queries) GetLoads(ctx context.Context, arg GetLoadsParams) ([]GetLoadsRow, error) {
rows, err := q.db.Query(ctx, getLoads,
arg.Limit,
arg.Offset,
arg.SearchCartridge,
arg.Cartridge,
arg.SearchBullet,
arg.Bullet,
arg.SearchBulletManufacturer,
arg.BulletManufacturer,
arg.SearchPrimer,
arg.Primer,
arg.SearchPrimerManufacturer,
arg.PrimeManufacturer,
arg.SearchPowder,
arg.Powder,
arg.SearchPowderManufacturer,
arg.PowderManufacturer,
arg.SearchCartridgeID,
arg.CartridgeID,
arg.SearchBulletID,
arg.BulletID,
arg.SearchPrimerID,
arg.PrimerID,
arg.SearchPowderID,
arg.PowderID,
arg.OrderBy,
)
if err != nil {
return nil, err
}
defer rows.Close()
var items []GetLoadsRow
for rows.Next() {
var i GetLoadsRow
if err := rows.Scan(
&i.ID,
&i.Col,
&i.PowderGr,
&i.CartridgeID,
&i.CartridgeName,
&i.CartridgeMeta,
&i.PowderID,
&i.PowderName,
&i.PowderMeta,
&i.PowderManufacturerName,
&i.PowderManufacturerUrl,
&i.PrimerID,
&i.PrimerName,
&i.PrimerMeta,
&i.PrimerManufacturerName,
&i.PrimerManufacturerUrl,
&i.BulletID,
&i.BulletName,
&i.BulletMeta,
&i.BulletWeight,
&i.BulletDiameter,
&i.BulletManufacturerName,
&i.BulletManufacturerUrl,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const totalLoads = `-- name: TotalLoads :one
select count(*)
from loads
`
func (q *Queries) TotalLoads(ctx context.Context) (int64, error) {
row := q.db.QueryRow(ctx, totalLoads)
var count int64
err := row.Scan(&count)
return count, err
}

View File

@@ -0,0 +1,65 @@
// Code generated by sqlc. DO NOT EDIT.
// versions:
// sqlc v1.27.0
package loads
import (
"github.com/jackc/pgx/v5/pgtype"
)
type Bullet struct {
ID pgtype.UUID `json:"id"`
Name string `json:"name"`
Weight int32 `json:"weight"`
Diameter int32 `json:"diameter"`
Meta []byte `json:"meta"`
Photo []byte `json:"photo"`
ManufacturerID pgtype.UUID `json:"manufacturer_id"`
CreatedAt pgtype.Timestamp `json:"created_at"`
}
type Cartridge struct {
ID pgtype.UUID `json:"id"`
Name string `json:"name"`
CreatedAt pgtype.Timestamp `json:"created_at"`
Meta []byte `json:"meta"`
}
type Load struct {
ID pgtype.UUID `json:"id"`
CartridgeID pgtype.UUID `json:"cartridge_id"`
Col float32 `json:"col"`
PowderID pgtype.UUID `json:"powder_id"`
PowderGr float32 `json:"powder_gr"`
PrimerID pgtype.UUID `json:"primer_id"`
BulletID pgtype.UUID `json:"bullet_id"`
Photo []byte `json:"photo"`
CreatedAt pgtype.Timestamp `json:"created_at"`
Meta []byte `json:"meta"`
}
type Manufacturer struct {
ID pgtype.UUID `json:"id"`
Name string `json:"name"`
Url pgtype.Text `json:"url"`
CreatedAt pgtype.Timestamp `json:"created_at"`
}
type Powder struct {
ID pgtype.UUID `json:"id"`
Name string `json:"name"`
Meta []byte `json:"meta"`
Photo []byte `json:"photo"`
ManufacturerID pgtype.UUID `json:"manufacturer_id"`
CreatedAt pgtype.Timestamp `json:"created_at"`
}
type Primer struct {
ID pgtype.UUID `json:"id"`
Name string `json:"name"`
Meta []byte `json:"meta"`
Photo []byte `json:"photo"`
ManufacturerID pgtype.UUID `json:"manufacturer_id"`
CreatedAt pgtype.Timestamp `json:"created_at"`
}

View File

@@ -0,0 +1,7 @@
create table manufacturers
(
id uuid primary key ,
name varchar(255) not null,
url varchar(255),
created_at timestamp default NOW() not null
);

View File

@@ -0,0 +1,23 @@
-- name: GetAll :many
select id, name, url, created_at
from manufacturers
order by name;
-- name: CreateManufacturer :exec
insert into manufacturers (id, name, url) values ($1, $2, $3);
-- name: UpdateManufacturer :exec
update manufacturers
set name=$1,
url=$2
where id = $3;
-- name: GetById :one
select id, name, url, created_at
from manufacturers
where id = $1;
-- name: DeleteById :exec
delete
from manufacturers
where id = $1;

View File

@@ -0,0 +1,32 @@
// Code generated by sqlc. DO NOT EDIT.
// versions:
// sqlc v1.27.0
package manufacturer
import (
"context"
"github.com/jackc/pgx/v5"
"github.com/jackc/pgx/v5/pgconn"
)
type DBTX interface {
Exec(context.Context, string, ...interface{}) (pgconn.CommandTag, error)
Query(context.Context, string, ...interface{}) (pgx.Rows, error)
QueryRow(context.Context, string, ...interface{}) pgx.Row
}
func New(db DBTX) *Queries {
return &Queries{db: db}
}
type Queries struct {
db DBTX
}
func (q *Queries) WithTx(tx pgx.Tx) *Queries {
return &Queries{
db: tx,
}
}

View File

@@ -0,0 +1,105 @@
// Code generated by sqlc. DO NOT EDIT.
// versions:
// sqlc v1.27.0
// source: manufacturer.sql
package manufacturer
import (
"context"
"github.com/jackc/pgx/v5/pgtype"
)
const createManufacturer = `-- name: CreateManufacturer :exec
insert into manufacturers (id, name, url) values ($1, $2, $3)
`
type CreateManufacturerParams struct {
ID pgtype.UUID `json:"id"`
Name string `json:"name"`
Url pgtype.Text `json:"url"`
}
func (q *Queries) CreateManufacturer(ctx context.Context, arg CreateManufacturerParams) error {
_, err := q.db.Exec(ctx, createManufacturer, arg.ID, arg.Name, arg.Url)
return err
}
const deleteById = `-- name: DeleteById :exec
delete
from manufacturers
where id = $1
`
func (q *Queries) DeleteById(ctx context.Context, id pgtype.UUID) error {
_, err := q.db.Exec(ctx, deleteById, id)
return err
}
const getAll = `-- name: GetAll :many
select id, name, url, created_at
from manufacturers
order by name
`
func (q *Queries) GetAll(ctx context.Context) ([]Manufacturer, error) {
rows, err := q.db.Query(ctx, getAll)
if err != nil {
return nil, err
}
defer rows.Close()
var items []Manufacturer
for rows.Next() {
var i Manufacturer
if err := rows.Scan(
&i.ID,
&i.Name,
&i.Url,
&i.CreatedAt,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const getById = `-- name: GetById :one
select id, name, url, created_at
from manufacturers
where id = $1
`
func (q *Queries) GetById(ctx context.Context, id pgtype.UUID) (Manufacturer, error) {
row := q.db.QueryRow(ctx, getById, id)
var i Manufacturer
err := row.Scan(
&i.ID,
&i.Name,
&i.Url,
&i.CreatedAt,
)
return i, err
}
const updateManufacturer = `-- name: UpdateManufacturer :exec
update manufacturers
set name=$1,
url=$2
where id = $3
`
type UpdateManufacturerParams struct {
Name string `json:"name"`
Url pgtype.Text `json:"url"`
ID pgtype.UUID `json:"id"`
}
func (q *Queries) UpdateManufacturer(ctx context.Context, arg UpdateManufacturerParams) error {
_, err := q.db.Exec(ctx, updateManufacturer, arg.Name, arg.Url, arg.ID)
return err
}

View File

@@ -0,0 +1,16 @@
// Code generated by sqlc. DO NOT EDIT.
// versions:
// sqlc v1.27.0
package manufacturer
import (
"github.com/jackc/pgx/v5/pgtype"
)
type Manufacturer struct {
ID pgtype.UUID `json:"id"`
Name string `json:"name"`
Url pgtype.Text `json:"url"`
CreatedAt pgtype.Timestamp `json:"created_at"`
}

View File

@@ -0,0 +1,19 @@
create table powders
(
id uuid primary key,
name varchar(255) not null,
meta json,
photo bytea,
manufacturer_id uuid not null,
created_at timestamp default NOW() not null,
constraint powders_manufacturers_id_fk
foreign key (manufacturer_id) references manufacturers (id)
);
create table manufacturers
(
id uuid primary key ,
name varchar(255) not null,
url varchar(255),
created_at timestamp default NOW() not null
);

41
backend/models/powder.sql Normal file
View File

@@ -0,0 +1,41 @@
-- name: GetPowderById :one
select powders.id as id,
powders.name as name,
powders.created_at,
powders.photo,
meta,
m.id as manufacturer_id,
m.name as manufacturer_name,
m.url as manufacturer_url
from powders
join manufacturers m on m.id = powders.manufacturer_id
where powders.id = $1;
-- name: GetPowders :many
select powders.id as id,
powders.name as name,
powders.created_at,
meta,
m.id as manufacturer_id,
m.name as manufacturer_name,
m.url as manufacturer_url
from powders
join manufacturers m on m.id = powders.manufacturer_id
order by powders.name desc;
-- name: DeletePowder :exec
DELETE
FROM powders
WHERE id = $1;
-- name: InsertPowder :exec
insert into powders (id, name, manufacturer_id, meta, photo)
values ($1, $2, $3, $4, $5);
-- name: UpdatePowder :exec
update powders
set name = $1,
manufacturer_id = $2,
meta = $3,
photo = $4
where id = $5;

View File

@@ -0,0 +1,32 @@
// Code generated by sqlc. DO NOT EDIT.
// versions:
// sqlc v1.27.0
package powder
import (
"context"
"github.com/jackc/pgx/v5"
"github.com/jackc/pgx/v5/pgconn"
)
type DBTX interface {
Exec(context.Context, string, ...interface{}) (pgconn.CommandTag, error)
Query(context.Context, string, ...interface{}) (pgx.Rows, error)
QueryRow(context.Context, string, ...interface{}) pgx.Row
}
func New(db DBTX) *Queries {
return &Queries{db: db}
}
type Queries struct {
db DBTX
}
func (q *Queries) WithTx(tx pgx.Tx) *Queries {
return &Queries{
db: tx,
}
}

View File

@@ -0,0 +1,25 @@
// Code generated by sqlc. DO NOT EDIT.
// versions:
// sqlc v1.27.0
package powder
import (
"github.com/jackc/pgx/v5/pgtype"
)
type Manufacturer struct {
ID pgtype.UUID `json:"id"`
Name string `json:"name"`
Url pgtype.Text `json:"url"`
CreatedAt pgtype.Timestamp `json:"created_at"`
}
type Powder struct {
ID pgtype.UUID `json:"id"`
Name string `json:"name"`
Meta []byte `json:"meta"`
Photo []byte `json:"photo"`
ManufacturerID pgtype.UUID `json:"manufacturer_id"`
CreatedAt pgtype.Timestamp `json:"created_at"`
}

View File

@@ -0,0 +1,167 @@
// Code generated by sqlc. DO NOT EDIT.
// versions:
// sqlc v1.27.0
// source: powder.sql
package powder
import (
"context"
"github.com/jackc/pgx/v5/pgtype"
)
const deletePowder = `-- name: DeletePowder :exec
DELETE
FROM powders
WHERE id = $1
`
func (q *Queries) DeletePowder(ctx context.Context, id pgtype.UUID) error {
_, err := q.db.Exec(ctx, deletePowder, id)
return err
}
const getPowderById = `-- name: GetPowderById :one
select powders.id as id,
powders.name as name,
powders.created_at,
powders.photo,
meta,
m.id as manufacturer_id,
m.name as manufacturer_name,
m.url as manufacturer_url
from powders
join manufacturers m on m.id = powders.manufacturer_id
where powders.id = $1
`
type GetPowderByIdRow struct {
ID pgtype.UUID `json:"id"`
Name string `json:"name"`
CreatedAt pgtype.Timestamp `json:"created_at"`
Photo []byte `json:"photo"`
Meta []byte `json:"meta"`
ManufacturerID pgtype.UUID `json:"manufacturer_id"`
ManufacturerName string `json:"manufacturer_name"`
ManufacturerUrl pgtype.Text `json:"manufacturer_url"`
}
func (q *Queries) GetPowderById(ctx context.Context, id pgtype.UUID) (GetPowderByIdRow, error) {
row := q.db.QueryRow(ctx, getPowderById, id)
var i GetPowderByIdRow
err := row.Scan(
&i.ID,
&i.Name,
&i.CreatedAt,
&i.Photo,
&i.Meta,
&i.ManufacturerID,
&i.ManufacturerName,
&i.ManufacturerUrl,
)
return i, err
}
const getPowders = `-- name: GetPowders :many
select powders.id as id,
powders.name as name,
powders.created_at,
meta,
m.id as manufacturer_id,
m.name as manufacturer_name,
m.url as manufacturer_url
from powders
join manufacturers m on m.id = powders.manufacturer_id
order by powders.name desc
`
type GetPowdersRow struct {
ID pgtype.UUID `json:"id"`
Name string `json:"name"`
CreatedAt pgtype.Timestamp `json:"created_at"`
Meta []byte `json:"meta"`
ManufacturerID pgtype.UUID `json:"manufacturer_id"`
ManufacturerName string `json:"manufacturer_name"`
ManufacturerUrl pgtype.Text `json:"manufacturer_url"`
}
func (q *Queries) GetPowders(ctx context.Context) ([]GetPowdersRow, error) {
rows, err := q.db.Query(ctx, getPowders)
if err != nil {
return nil, err
}
defer rows.Close()
var items []GetPowdersRow
for rows.Next() {
var i GetPowdersRow
if err := rows.Scan(
&i.ID,
&i.Name,
&i.CreatedAt,
&i.Meta,
&i.ManufacturerID,
&i.ManufacturerName,
&i.ManufacturerUrl,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const insertPowder = `-- name: InsertPowder :exec
insert into powders (id, name, manufacturer_id, meta, photo)
values ($1, $2, $3, $4, $5)
`
type InsertPowderParams struct {
ID pgtype.UUID `json:"id"`
Name string `json:"name"`
ManufacturerID pgtype.UUID `json:"manufacturer_id"`
Meta []byte `json:"meta"`
Photo []byte `json:"photo"`
}
func (q *Queries) InsertPowder(ctx context.Context, arg InsertPowderParams) error {
_, err := q.db.Exec(ctx, insertPowder,
arg.ID,
arg.Name,
arg.ManufacturerID,
arg.Meta,
arg.Photo,
)
return err
}
const updatePowder = `-- name: UpdatePowder :exec
update powders
set name = $1,
manufacturer_id = $2,
meta = $3,
photo = $4
where id = $5
`
type UpdatePowderParams struct {
Name string `json:"name"`
ManufacturerID pgtype.UUID `json:"manufacturer_id"`
Meta []byte `json:"meta"`
Photo []byte `json:"photo"`
ID pgtype.UUID `json:"id"`
}
func (q *Queries) UpdatePowder(ctx context.Context, arg UpdatePowderParams) error {
_, err := q.db.Exec(ctx, updatePowder,
arg.Name,
arg.ManufacturerID,
arg.Meta,
arg.Photo,
arg.ID,
)
return err
}

View File

@@ -0,0 +1,19 @@
create table primers
(
id uuid primary key,
name varchar(255) not null,
meta json,
photo bytea,
manufacturer_id uuid not null,
created_at timestamp default NOW() not null,
constraint primers_manufacturers_id_fk
foreign key (manufacturer_id) references manufacturers (id)
);
create table manufacturers
(
id uuid primary key ,
name varchar(255) not null,
url varchar(255),
created_at timestamp default NOW() not null
);

View File

@@ -0,0 +1,41 @@
-- name: GetPrimers :many
SELECT primers.id as id,
primers.name as name,
primers.meta as meta,
primers.created_at as created_at,
m.id as manufacturer_id,
m.name as manufacturer_name,
m.url as manufacturer_url
FROM primers
join manufacturers m on m.id = primers.manufacturer_id
ORDER BY primers.name desc;
-- name: GetPrimerById :one
SELECT primers.id as id,
primers.name as name,
primers.meta as meta,
primers.photo as photo,
primers.created_at as created_at,
m.id as manufacturer_id,
m.name as manufacturer_name,
m.url as manufacturer_url
FROM primers
join manufacturers m on m.id = primers.manufacturer_id
WHERE primers.id = $1;
-- name: InsertPrimer :exec
INSERT INTO primers (id, name, manufacturer_id, meta, photo)
VALUES ($1, $2, $3, $4, $5);
-- name: DeletePrimer :exec
DELETE
FROM primers
WHERE id = $1;
-- name: UpdatePrimer :exec
UPDATE primers
SET name = $1,
manufacturer_id = $2,
meta = $3,
photo = $4
WHERE id = $5;

View File

@@ -0,0 +1,32 @@
// Code generated by sqlc. DO NOT EDIT.
// versions:
// sqlc v1.27.0
package primers
import (
"context"
"github.com/jackc/pgx/v5"
"github.com/jackc/pgx/v5/pgconn"
)
type DBTX interface {
Exec(context.Context, string, ...interface{}) (pgconn.CommandTag, error)
Query(context.Context, string, ...interface{}) (pgx.Rows, error)
QueryRow(context.Context, string, ...interface{}) pgx.Row
}
func New(db DBTX) *Queries {
return &Queries{db: db}
}
type Queries struct {
db DBTX
}
func (q *Queries) WithTx(tx pgx.Tx) *Queries {
return &Queries{
db: tx,
}
}

View File

@@ -0,0 +1,25 @@
// Code generated by sqlc. DO NOT EDIT.
// versions:
// sqlc v1.27.0
package primers
import (
"github.com/jackc/pgx/v5/pgtype"
)
type Manufacturer struct {
ID pgtype.UUID `json:"id"`
Name string `json:"name"`
Url pgtype.Text `json:"url"`
CreatedAt pgtype.Timestamp `json:"created_at"`
}
type Primer struct {
ID pgtype.UUID `json:"id"`
Name string `json:"name"`
Meta []byte `json:"meta"`
Photo []byte `json:"photo"`
ManufacturerID pgtype.UUID `json:"manufacturer_id"`
CreatedAt pgtype.Timestamp `json:"created_at"`
}

View File

@@ -0,0 +1,167 @@
// Code generated by sqlc. DO NOT EDIT.
// versions:
// sqlc v1.27.0
// source: primers.sql
package primers
import (
"context"
"github.com/jackc/pgx/v5/pgtype"
)
const deletePrimer = `-- name: DeletePrimer :exec
DELETE
FROM primers
WHERE id = $1
`
func (q *Queries) DeletePrimer(ctx context.Context, id pgtype.UUID) error {
_, err := q.db.Exec(ctx, deletePrimer, id)
return err
}
const getPrimerById = `-- name: GetPrimerById :one
SELECT primers.id as id,
primers.name as name,
primers.meta as meta,
primers.photo as photo,
primers.created_at as created_at,
m.id as manufacturer_id,
m.name as manufacturer_name,
m.url as manufacturer_url
FROM primers
join manufacturers m on m.id = primers.manufacturer_id
WHERE primers.id = $1
`
type GetPrimerByIdRow struct {
ID pgtype.UUID `json:"id"`
Name string `json:"name"`
Meta []byte `json:"meta"`
Photo []byte `json:"photo"`
CreatedAt pgtype.Timestamp `json:"created_at"`
ManufacturerID pgtype.UUID `json:"manufacturer_id"`
ManufacturerName string `json:"manufacturer_name"`
ManufacturerUrl pgtype.Text `json:"manufacturer_url"`
}
func (q *Queries) GetPrimerById(ctx context.Context, id pgtype.UUID) (GetPrimerByIdRow, error) {
row := q.db.QueryRow(ctx, getPrimerById, id)
var i GetPrimerByIdRow
err := row.Scan(
&i.ID,
&i.Name,
&i.Meta,
&i.Photo,
&i.CreatedAt,
&i.ManufacturerID,
&i.ManufacturerName,
&i.ManufacturerUrl,
)
return i, err
}
const getPrimers = `-- name: GetPrimers :many
SELECT primers.id as id,
primers.name as name,
primers.meta as meta,
primers.created_at as created_at,
m.id as manufacturer_id,
m.name as manufacturer_name,
m.url as manufacturer_url
FROM primers
join manufacturers m on m.id = primers.manufacturer_id
ORDER BY primers.name desc
`
type GetPrimersRow struct {
ID pgtype.UUID `json:"id"`
Name string `json:"name"`
Meta []byte `json:"meta"`
CreatedAt pgtype.Timestamp `json:"created_at"`
ManufacturerID pgtype.UUID `json:"manufacturer_id"`
ManufacturerName string `json:"manufacturer_name"`
ManufacturerUrl pgtype.Text `json:"manufacturer_url"`
}
func (q *Queries) GetPrimers(ctx context.Context) ([]GetPrimersRow, error) {
rows, err := q.db.Query(ctx, getPrimers)
if err != nil {
return nil, err
}
defer rows.Close()
var items []GetPrimersRow
for rows.Next() {
var i GetPrimersRow
if err := rows.Scan(
&i.ID,
&i.Name,
&i.Meta,
&i.CreatedAt,
&i.ManufacturerID,
&i.ManufacturerName,
&i.ManufacturerUrl,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const insertPrimer = `-- name: InsertPrimer :exec
INSERT INTO primers (id, name, manufacturer_id, meta, photo)
VALUES ($1, $2, $3, $4, $5)
`
type InsertPrimerParams struct {
ID pgtype.UUID `json:"id"`
Name string `json:"name"`
ManufacturerID pgtype.UUID `json:"manufacturer_id"`
Meta []byte `json:"meta"`
Photo []byte `json:"photo"`
}
func (q *Queries) InsertPrimer(ctx context.Context, arg InsertPrimerParams) error {
_, err := q.db.Exec(ctx, insertPrimer,
arg.ID,
arg.Name,
arg.ManufacturerID,
arg.Meta,
arg.Photo,
)
return err
}
const updatePrimer = `-- name: UpdatePrimer :exec
UPDATE primers
SET name = $1,
manufacturer_id = $2,
meta = $3,
photo = $4
WHERE id = $5
`
type UpdatePrimerParams struct {
Name string `json:"name"`
ManufacturerID pgtype.UUID `json:"manufacturer_id"`
Meta []byte `json:"meta"`
Photo []byte `json:"photo"`
ID pgtype.UUID `json:"id"`
}
func (q *Queries) UpdatePrimer(ctx context.Context, arg UpdatePrimerParams) error {
_, err := q.db.Exec(ctx, updatePrimer,
arg.Name,
arg.ManufacturerID,
arg.Meta,
arg.Photo,
arg.ID,
)
return err
}

47
backend/models/sqlc.yaml Normal file
View File

@@ -0,0 +1,47 @@
version: "2"
sql:
- schema: "bullets-schema.sql"
engine: "postgresql"
queries: "bullets.sql"
gen:
go:
package: "bullets"
out: "bullets"
emit_json_tags: true
sql_package: "pgx/v5"
- schema: "manufacturer-schema.sql"
engine: "postgresql"
queries: "manufacturer.sql"
gen:
go:
package: "manufacturer"
out: "manufacturer"
emit_json_tags: true
sql_package: "pgx/v5"
- schema: "primers-schema.sql"
engine: "postgresql"
queries: "primers.sql"
gen:
go:
package: "primers"
out: "primers"
emit_json_tags: true
sql_package: "pgx/v5"
- schema: "powder-schema.sql"
engine: "postgresql"
queries: "powder.sql"
gen:
go:
package: "powder"
out: "powder"
emit_json_tags: true
sql_package: "pgx/v5"
- schema: "loads-schema.sql"
engine: "postgresql"
queries: "loads.sql"
gen:
go:
package: "loads"
out: "loads"
emit_json_tags: true
sql_package: "pgx/v5"