1
0
Fork 0

refactor: use serial as id instead of uuid

This commit is contained in:
Vojtěch Mareš 2024-06-23 12:40:55 +02:00
parent 18b033add1
commit 370531a9a5
Signed by: vojtech.mares
GPG key ID: C6827B976F17240D
11 changed files with 319 additions and 381 deletions

View file

@ -546,8 +546,8 @@ components:
- id - id
TrainingID: TrainingID:
type: string type: integer
format: uuid minimum: 1
x-go-type: training.TrainingID x-go-type: training.TrainingID
x-go-type-import: x-go-type-import:
path: gitlab.mareshq.com/hq/yggdrasil/pkg/training path: gitlab.mareshq.com/hq/yggdrasil/pkg/training
@ -652,8 +652,8 @@ components:
- id - id
TrainingDateID: TrainingDateID:
type: string type: integer
format: uuid minimum: 1
x-go-type: training.TrainingDateID x-go-type: training.TrainingDateID
x-go-type-import: x-go-type-import:
path: gitlab.mareshq.com/hq/yggdrasil/pkg/training path: gitlab.mareshq.com/hq/yggdrasil/pkg/training
@ -705,8 +705,8 @@ components:
- attended - attended
TrainingDateAttendeeID: TrainingDateAttendeeID:
type: string type: integer
format: uuid minimum: 1
x-go-type: training.TrainingDateAttendeeID x-go-type: training.TrainingDateAttendeeID
x-go-type-import: x-go-type-import:
path: gitlab.mareshq.com/hq/yggdrasil/pkg/training path: gitlab.mareshq.com/hq/yggdrasil/pkg/training

View file

@ -5,7 +5,6 @@ import (
pgxDeciaml "github.com/jackc/pgx-shopspring-decimal" pgxDeciaml "github.com/jackc/pgx-shopspring-decimal"
"github.com/jackc/pgx/v5" "github.com/jackc/pgx/v5"
"github.com/jackc/pgx/v5/pgxpool" "github.com/jackc/pgx/v5/pgxpool"
pgxUUID "github.com/vgarvardt/pgx-google-uuid/v5"
"gitlab.mareshq.com/hq/yggdrasil/internal/bootstrap" "gitlab.mareshq.com/hq/yggdrasil/internal/bootstrap"
"gitlab.mareshq.com/hq/yggdrasil/internal/faker" "gitlab.mareshq.com/hq/yggdrasil/internal/faker"
"gitlab.mareshq.com/hq/yggdrasil/pkg/training" "gitlab.mareshq.com/hq/yggdrasil/pkg/training"
@ -44,7 +43,6 @@ func main() {
} }
pgxConfig.AfterConnect = func(ctx context.Context, conn *pgx.Conn) error { pgxConfig.AfterConnect = func(ctx context.Context, conn *pgx.Conn) error {
pgxUUID.Register(conn.TypeMap())
pgxDeciaml.Register(conn.TypeMap()) pgxDeciaml.Register(conn.TypeMap())
return nil return nil
} }

3
go.mod
View file

@ -7,14 +7,12 @@ require (
github.com/gofiber/contrib/fiberzap/v2 v2.1.3 github.com/gofiber/contrib/fiberzap/v2 v2.1.3
github.com/gofiber/contrib/swagger v1.1.2 github.com/gofiber/contrib/swagger v1.1.2
github.com/gofiber/fiber/v2 v2.52.4 github.com/gofiber/fiber/v2 v2.52.4
github.com/google/uuid v1.6.0
github.com/jackc/pgx-shopspring-decimal v0.0.0-20220624020537-1d36b5a1853e github.com/jackc/pgx-shopspring-decimal v0.0.0-20220624020537-1d36b5a1853e
github.com/jackc/pgx/v5 v5.6.0 github.com/jackc/pgx/v5 v5.6.0
github.com/oapi-codegen/fiber-middleware v1.0.2 github.com/oapi-codegen/fiber-middleware v1.0.2
github.com/oapi-codegen/runtime v1.1.1 github.com/oapi-codegen/runtime v1.1.1
github.com/shopspring/decimal v1.4.0 github.com/shopspring/decimal v1.4.0
github.com/stretchr/testify v1.9.0 github.com/stretchr/testify v1.9.0
github.com/vgarvardt/pgx-google-uuid/v5 v5.6.0
go.uber.org/zap v1.27.0 go.uber.org/zap v1.27.0
) )
@ -34,6 +32,7 @@ require (
github.com/go-openapi/swag v0.23.0 // indirect github.com/go-openapi/swag v0.23.0 // indirect
github.com/go-openapi/validate v0.24.0 // indirect github.com/go-openapi/validate v0.24.0 // indirect
github.com/google/go-cmp v0.6.0 // indirect github.com/google/go-cmp v0.6.0 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/gorilla/mux v1.8.1 // indirect github.com/gorilla/mux v1.8.1 // indirect
github.com/invopop/yaml v0.3.1 // indirect github.com/invopop/yaml v0.3.1 // indirect
github.com/jackc/pgpassfile v1.0.0 // indirect github.com/jackc/pgpassfile v1.0.0 // indirect

2
go.sum
View file

@ -111,8 +111,6 @@ github.com/valyala/fasthttp v1.55.0 h1:Zkefzgt6a7+bVKHnu/YaYSOPfNYNisSVBo/unVCf8
github.com/valyala/fasthttp v1.55.0/go.mod h1:NkY9JtkrpPKmgwV3HTaS2HWaJss9RSIsRVfcxxoHiOM= github.com/valyala/fasthttp v1.55.0/go.mod h1:NkY9JtkrpPKmgwV3HTaS2HWaJss9RSIsRVfcxxoHiOM=
github.com/valyala/tcplisten v1.0.0 h1:rBHj/Xf+E1tRGZyWIWwJDiRY0zc1Js+CV5DqwacVSA8= github.com/valyala/tcplisten v1.0.0 h1:rBHj/Xf+E1tRGZyWIWwJDiRY0zc1Js+CV5DqwacVSA8=
github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc= github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc=
github.com/vgarvardt/pgx-google-uuid/v5 v5.6.0 h1:EhPtK0mgrgaTMXpegE69hvoSOVC1Ahk8+QJ9B8b+OdU=
github.com/vgarvardt/pgx-google-uuid/v5 v5.6.0/go.mod h1:5LtFrNEkgzxHvXPO9eOvcXsSn9/KeKYgx9kjeI2oXQI=
go.mongodb.org/mongo-driver v1.15.1 h1:l+RvoUOoMXFmADTLfYDm7On9dRm7p4T80/lEQM+r7HU= go.mongodb.org/mongo-driver v1.15.1 h1:l+RvoUOoMXFmADTLfYDm7On9dRm7p4T80/lEQM+r7HU=
go.mongodb.org/mongo-driver v1.15.1/go.mod h1:Vzb0Mk/pa7e6cWw85R4F/endUC3u0U9jGcNU603k65c= go.mongodb.org/mongo-driver v1.15.1/go.mod h1:Vzb0Mk/pa7e6cWw85R4F/endUC3u0U9jGcNU603k65c=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=

View file

@ -5,7 +5,6 @@ import (
pgxDeciaml "github.com/jackc/pgx-shopspring-decimal" pgxDeciaml "github.com/jackc/pgx-shopspring-decimal"
"github.com/jackc/pgx/v5" "github.com/jackc/pgx/v5"
"github.com/jackc/pgx/v5/pgxpool" "github.com/jackc/pgx/v5/pgxpool"
pgxUUID "github.com/vgarvardt/pgx-google-uuid/v5"
"gitlab.mareshq.com/hq/yggdrasil/internal/faker" "gitlab.mareshq.com/hq/yggdrasil/internal/faker"
"gitlab.mareshq.com/hq/yggdrasil/internal/server" "gitlab.mareshq.com/hq/yggdrasil/internal/server"
"gitlab.mareshq.com/hq/yggdrasil/pkg/training" "gitlab.mareshq.com/hq/yggdrasil/pkg/training"
@ -48,7 +47,6 @@ func Bootstrap(logger *zap.Logger) *server.Server {
} }
pgxConfig.AfterConnect = func(ctx context.Context, conn *pgx.Conn) error { pgxConfig.AfterConnect = func(ctx context.Context, conn *pgx.Conn) error {
pgxUUID.Register(conn.TypeMap())
pgxDeciaml.Register(conn.TypeMap()) pgxDeciaml.Register(conn.TypeMap())
return nil return nil
} }

View file

@ -2356,24 +2356,24 @@ var swaggerSpec = []string{
"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",
} }
// GetSwagger returns the content of the embedded swagger specification file // GetSwagger returns the content of the embedded swagger specification file

View file

@ -3,8 +3,8 @@ package server
import ( import (
"bytes" "bytes"
"encoding/json" "encoding/json"
"fmt"
"github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2"
"github.com/google/uuid"
"github.com/oapi-codegen/runtime/types" "github.com/oapi-codegen/runtime/types"
"github.com/shopspring/decimal" "github.com/shopspring/decimal"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
@ -128,7 +128,7 @@ func TestServer(t *testing.T) {
}) })
t.Run("Training not found", func(t *testing.T) { t.Run("Training not found", func(t *testing.T) {
rr, _ := doGet(t, app, "/v1/trainings/97b0e954-14f3-4908-98fa-271f505056d3") rr, _ := doGet(t, app, fmt.Sprintf("/v1/trainings/%d", 9999999))
assert.Equal(t, http.StatusNotFound, rr.StatusCode) assert.Equal(t, http.StatusNotFound, rr.StatusCode)
var trainingError NotFoundError var trainingError NotFoundError
@ -190,7 +190,7 @@ func TestServer(t *testing.T) {
}, },
} }
rr, _ := doPut(t, app, "/v1/trainings/"+tr.ID.String(), updTr) rr, _ := doPut(t, app, fmt.Sprintf("/v1/trainings/%d", tr.ID), updTr)
assert.Equal(t, http.StatusOK, rr.StatusCode) assert.Equal(t, http.StatusOK, rr.StatusCode)
var trr Training var trr Training
@ -215,7 +215,7 @@ func TestServer(t *testing.T) {
_ = handlers.trainingRepository.Create(tr) _ = handlers.trainingRepository.Create(tr)
rr, _ := doGet(t, app, "/v1/trainings/"+tr.ID.String()) rr, _ := doGet(t, app, fmt.Sprintf("/v1/trainings/%d", tr.ID))
assert.Equal(t, http.StatusOK, rr.StatusCode) assert.Equal(t, http.StatusOK, rr.StatusCode)
var trr Training var trr Training
@ -223,10 +223,10 @@ func TestServer(t *testing.T) {
assert.NoError(t, err, "error unmarshalling response") assert.NoError(t, err, "error unmarshalling response")
assert.Equal(t, tr.ID, trr.Id) assert.Equal(t, tr.ID, trr.Id)
drr, _ := doDelete(t, app, "/v1/trainings/"+tr.ID.String()) drr, _ := doDelete(t, app, fmt.Sprintf("/v1/trainings/%d", tr.ID))
assert.Equal(t, http.StatusNoContent, drr.StatusCode) assert.Equal(t, http.StatusNoContent, drr.StatusCode)
rr, _ = doGet(t, app, "/v1/trainings/"+tr.ID.String()) rr, _ = doGet(t, app, fmt.Sprintf("/v1/trainings/%d", tr.ID))
assert.Equal(t, http.StatusNotFound, rr.StatusCode) assert.Equal(t, http.StatusNotFound, rr.StatusCode)
var trainingError NotFoundError var trainingError NotFoundError
@ -271,7 +271,7 @@ func TestServer(t *testing.T) {
}, },
} }
rr, err := doPost(t, app, "/v1/trainings/"+tr.ID.String()+"/dates", newTrainingDate) rr, err := doPost(t, app, fmt.Sprintf("/v1/trainings/%d/dates", tr.ID), newTrainingDate)
assert.Equal(t, http.StatusCreated, rr.StatusCode) assert.Equal(t, http.StatusCreated, rr.StatusCode)
@ -304,7 +304,7 @@ func TestServer(t *testing.T) {
_ = handlers.trainingRepository.Create(tr) _ = handlers.trainingRepository.Create(tr)
rr, _ := doGet(t, app, "/v1/trainings/"+tr.ID.String()+"/dates/97b0e954-14f3-4908-98fa-271f505056d3") rr, _ := doGet(t, app, fmt.Sprintf("/v1/trainings/%d/dates/%d", tr.ID, 999999))
assert.Equal(t, http.StatusNotFound, rr.StatusCode) assert.Equal(t, http.StatusNotFound, rr.StatusCode)
var trainingError NotFoundError var trainingError NotFoundError
@ -331,17 +331,15 @@ func TestServer(t *testing.T) {
date := time.Date(2024, time.May, 1, 0, 0, 0, 0, time.UTC) date := time.Date(2024, time.May, 1, 0, 0, 0, 0, time.UTC)
td := &training.TrainingDate{ td := &training.TrainingDate{
Address: "Test Address 123, NYC", Address: "Test Address 123, NYC",
Capacity: 12, Capacity: 12,
Date: date, Date: date,
Days: tr.Days, Days: tr.Days,
IsOnline: false, IsOnline: false,
Location: "NYC", Location: "NYC",
StartTime: date, StartTime: date,
Price: money.Money{ PriceAmount: decimal.NewFromInt(200),
Amount: decimal.NewFromInt(200), PriceCurrency: "EUR",
Currency: "EUR",
},
} }
trainingCount := 5 trainingCount := 5
@ -350,7 +348,7 @@ func TestServer(t *testing.T) {
_ = handlers.trainingDateRepository.Create(tr.ID, td) _ = handlers.trainingDateRepository.Create(tr.ID, td)
} }
rr, _ := doGet(t, app, "/v1/trainings/"+tr.ID.String()+"/dates") rr, _ := doGet(t, app, fmt.Sprintf("/v1/trainings/%d/dates", tr.ID))
assert.Equal(t, http.StatusOK, rr.StatusCode) assert.Equal(t, http.StatusOK, rr.StatusCode)
var trainingDates []TrainingDate var trainingDates []TrainingDate
@ -377,17 +375,15 @@ func TestServer(t *testing.T) {
date := time.Date(2024, time.May, 1, 0, 0, 0, 0, time.UTC) date := time.Date(2024, time.May, 1, 0, 0, 0, 0, time.UTC)
td := &training.TrainingDate{ td := &training.TrainingDate{
Address: "Test Address 123, NYC", Address: "Test Address 123, NYC",
Capacity: 12, Capacity: 12,
Date: date, Date: date,
Days: tr.Days, Days: tr.Days,
IsOnline: false, IsOnline: false,
Location: "NYC", Location: "NYC",
StartTime: date, StartTime: date,
Price: money.Money{ PriceAmount: decimal.NewFromInt(200),
Amount: decimal.NewFromInt(200), PriceCurrency: "EUR",
Currency: "EUR",
},
} }
_ = handlers.trainingDateRepository.Create(tr.ID, td) _ = handlers.trainingDateRepository.Create(tr.ID, td)
@ -406,7 +402,7 @@ func TestServer(t *testing.T) {
}, },
} }
rr, _ := doPut(t, app, "/v1/trainings/"+tr.ID.String()+"/dates/"+td.ID.String(), updTd) rr, _ := doPut(t, app, fmt.Sprintf("/v1/trainings/%d/dates/%d", tr.ID, td.ID), updTd)
assert.Equal(t, http.StatusOK, rr.StatusCode) assert.Equal(t, http.StatusOK, rr.StatusCode)
var tdrr TrainingDate var tdrr TrainingDate
@ -440,22 +436,20 @@ func TestServer(t *testing.T) {
date := time.Date(2024, time.May, 1, 0, 0, 0, 0, time.UTC) date := time.Date(2024, time.May, 1, 0, 0, 0, 0, time.UTC)
td := &training.TrainingDate{ td := &training.TrainingDate{
Address: "Test Address 123, NYC", Address: "Test Address 123, NYC",
Capacity: 12, Capacity: 12,
Date: date, Date: date,
Days: tr.Days, Days: tr.Days,
IsOnline: false, IsOnline: false,
Location: "NYC", Location: "NYC",
StartTime: date, StartTime: date,
Price: money.Money{ PriceAmount: decimal.NewFromInt(200),
Amount: decimal.NewFromInt(200), PriceCurrency: "EUR",
Currency: "EUR",
},
} }
_ = handlers.trainingDateRepository.Create(tr.ID, td) _ = handlers.trainingDateRepository.Create(tr.ID, td)
rr, _ := doGet(t, app, "/v1/trainings/"+tr.ID.String()+"/dates/"+td.ID.String()) rr, _ := doGet(t, app, fmt.Sprintf("/v1/trainings/%d/dates/%d", tr.ID, td.ID))
assert.Equal(t, http.StatusOK, rr.StatusCode) assert.Equal(t, http.StatusOK, rr.StatusCode)
var tdrr TrainingDate var tdrr TrainingDate
@ -463,10 +457,10 @@ func TestServer(t *testing.T) {
assert.NoError(t, err, "error unmarshalling response") assert.NoError(t, err, "error unmarshalling response")
assert.Equal(t, td.ID, tdrr.Id) assert.Equal(t, td.ID, tdrr.Id)
drr, _ := doDelete(t, app, "/v1/trainings/"+tr.ID.String()+"/dates/"+td.ID.String()) drr, _ := doDelete(t, app, fmt.Sprintf("/v1/trainings/%d/dates/%d", tr.ID, td.ID))
assert.Equal(t, http.StatusNoContent, drr.StatusCode) assert.Equal(t, http.StatusNoContent, drr.StatusCode)
rr, _ = doGet(t, app, "/v1/trainings/"+tr.ID.String()+"/dates/"+td.ID.String()) rr, _ = doGet(t, app, fmt.Sprintf("/v1/trainings/%d/dates/%d", tr.ID, td.ID))
assert.Equal(t, http.StatusNotFound, rr.StatusCode) assert.Equal(t, http.StatusNotFound, rr.StatusCode)
var trainingError NotFoundError var trainingError NotFoundError
@ -474,7 +468,7 @@ func TestServer(t *testing.T) {
assert.NoError(t, err, "error getting response", err) assert.NoError(t, err, "error getting response", err)
assert.Equal(t, http.StatusNotFound, trainingError.Status) assert.Equal(t, http.StatusNotFound, trainingError.Status)
lrr, _ := doGet(t, app, "/v1/trainings/"+tr.ID.String()+"/dates") lrr, _ := doGet(t, app, fmt.Sprintf("/v1/trainings/%d/dates", tr.ID))
assert.Equal(t, http.StatusOK, lrr.StatusCode) assert.Equal(t, http.StatusOK, lrr.StatusCode)
var trainingDates []TrainingDate var trainingDates []TrainingDate
@ -503,22 +497,20 @@ func TestServer(t *testing.T) {
for i := -4; i <= 5; i++ { for i := -4; i <= 5; i++ {
date := now.AddDate(0, 0, i) date := now.AddDate(0, 0, i)
td := &training.TrainingDate{ td := &training.TrainingDate{
Address: "Test Address 123, NYC", Address: "Test Address 123, NYC",
Capacity: 12, Capacity: 12,
Date: date, Date: date,
Days: tr.Days, Days: tr.Days,
IsOnline: false, IsOnline: false,
Location: "NYC", Location: "NYC",
StartTime: date, StartTime: date,
Price: money.Money{ PriceAmount: decimal.NewFromInt(200),
Amount: decimal.NewFromInt(200), PriceCurrency: "EUR",
Currency: "EUR",
},
} }
_ = handlers.trainingDateRepository.Create(tr.ID, td) _ = handlers.trainingDateRepository.Create(tr.ID, td)
} }
rr, _ := doGet(t, app, "/v1/trainings/"+tr.ID.String()+"/upcoming-dates") rr, _ := doGet(t, app, fmt.Sprintf("/v1/trainings/%d/upcoming-dates", tr.ID))
assert.Equal(t, http.StatusOK, rr.StatusCode) assert.Equal(t, http.StatusOK, rr.StatusCode)
var trainingDatesReturned []TrainingDate var trainingDatesReturned []TrainingDate
@ -577,47 +569,41 @@ func TestServer(t *testing.T) {
for i := -4; i <= upcomingTrainingCount; i++ { for i := -4; i <= upcomingTrainingCount; i++ {
date := now.AddDate(0, 0, i) date := now.AddDate(0, 0, i)
td1 := &training.TrainingDate{ td1 := &training.TrainingDate{
Address: "Test Address 123, NYC", Address: "Test Address 123, NYC",
Capacity: 12, Capacity: 12,
Date: date, Date: date,
Days: tr1.Days, Days: tr1.Days,
IsOnline: false, IsOnline: false,
Location: "NYC", Location: "NYC",
StartTime: date, StartTime: date,
Price: money.Money{ PriceAmount: decimal.NewFromInt(200),
Amount: decimal.NewFromInt(200), PriceCurrency: "EUR",
Currency: "EUR",
},
} }
_ = handlers.trainingDateRepository.Create(tr1.ID, td1) _ = handlers.trainingDateRepository.Create(tr1.ID, td1)
td2 := &training.TrainingDate{ td2 := &training.TrainingDate{
Address: "Test Address 123, NYC", Address: "Test Address 123, NYC",
Capacity: 12, Capacity: 12,
Date: date, Date: date,
Days: tr2.Days, Days: tr2.Days,
IsOnline: false, IsOnline: false,
Location: "NYC", Location: "NYC",
StartTime: date, StartTime: date,
Price: money.Money{ PriceAmount: decimal.NewFromInt(200),
Amount: decimal.NewFromInt(200), PriceCurrency: "EUR",
Currency: "EUR",
},
} }
_ = handlers.trainingDateRepository.Create(tr2.ID, td2) _ = handlers.trainingDateRepository.Create(tr2.ID, td2)
td3 := &training.TrainingDate{ td3 := &training.TrainingDate{
Address: "Test Address 123, NYC", Address: "Test Address 123, NYC",
Capacity: 12, Capacity: 12,
Date: date, Date: date,
Days: tr3.Days, Days: tr3.Days,
IsOnline: false, IsOnline: false,
Location: "NYC", Location: "NYC",
StartTime: date, StartTime: date,
Price: money.Money{ PriceAmount: decimal.NewFromInt(200),
Amount: decimal.NewFromInt(200), PriceCurrency: "EUR",
Currency: "EUR",
},
} }
_ = handlers.trainingDateRepository.Create(tr3.ID, td3) _ = handlers.trainingDateRepository.Create(tr3.ID, td3)
} }
@ -656,21 +642,19 @@ func TestServer(t *testing.T) {
date := time.Date(2024, time.May, 1, 9, 0, 0, 0, time.UTC) date := time.Date(2024, time.May, 1, 9, 0, 0, 0, time.UTC)
td := &training.TrainingDate{ td := &training.TrainingDate{
Address: "Test Address 123, NYC", Address: "Test Address 123, NYC",
Capacity: 12, Capacity: 12,
Date: date, Date: date,
Days: tr.Days, Days: tr.Days,
IsOnline: false, IsOnline: false,
Location: "NYC", Location: "NYC",
StartTime: date, StartTime: date,
Price: money.Money{ PriceAmount: decimal.NewFromInt(200),
Amount: decimal.NewFromInt(200), PriceCurrency: "EUR",
Currency: "EUR",
},
} }
_ = handlers.trainingDateRepository.Create(tr.ID, td) _ = handlers.trainingDateRepository.Create(tr.ID, td)
rr, _ := doGet(t, app, "/v1/trainings/"+tr.ID.String()+"/dates/"+td.ID.String()+"/attendees/"+uuid.New().String()) rr, _ := doGet(t, app, fmt.Sprintf("/v1/trainings/%d/dates/%d/attendees/%d", tr.ID, td.ID, 99999999))
assert.Equal(t, http.StatusNotFound, rr.StatusCode) assert.Equal(t, http.StatusNotFound, rr.StatusCode)
var notFound NotFoundError var notFound NotFoundError
@ -698,17 +682,15 @@ func TestServer(t *testing.T) {
date := time.Date(2024, time.May, 1, 9, 0, 0, 0, time.UTC) date := time.Date(2024, time.May, 1, 9, 0, 0, 0, time.UTC)
td := &training.TrainingDate{ td := &training.TrainingDate{
Address: "Test Address 123, NYC", Address: "Test Address 123, NYC",
Capacity: 12, Capacity: 12,
Date: date, Date: date,
Days: tr.Days, Days: tr.Days,
IsOnline: false, IsOnline: false,
Location: "NYC", Location: "NYC",
StartTime: date, StartTime: date,
Price: money.Money{ PriceAmount: decimal.NewFromInt(200),
Amount: decimal.NewFromInt(200), PriceCurrency: "EUR",
Currency: "EUR",
},
} }
_ = handlers.trainingDateRepository.Create(tr.ID, td) _ = handlers.trainingDateRepository.Create(tr.ID, td)
@ -721,7 +703,7 @@ func TestServer(t *testing.T) {
IsStudent: new(bool), IsStudent: new(bool),
} }
rr, _ := doPost(t, app, "/v1/trainings/"+tr.ID.String()+"/dates/"+td.ID.String()+"/attendees", newTrainingDateAttendee) rr, _ := doPost(t, app, fmt.Sprintf("/v1/trainings/%d/dates/%d/attendees", tr.ID, td.ID), newTrainingDateAttendee)
assert.Equal(t, http.StatusCreated, rr.StatusCode) assert.Equal(t, http.StatusCreated, rr.StatusCode)
var attendeeResponse TrainingDateAttendee var attendeeResponse TrainingDateAttendee
@ -733,8 +715,8 @@ func TestServer(t *testing.T) {
assert.Equal(t, newTrainingDateAttendee.Position, attendeeResponse.Position) assert.Equal(t, newTrainingDateAttendee.Position, attendeeResponse.Position)
assert.Equal(t, newTrainingDateAttendee.Phone, attendeeResponse.Phone) assert.Equal(t, newTrainingDateAttendee.Phone, attendeeResponse.Phone)
assert.Equal(t, newTrainingDateAttendee.IsStudent, attendeeResponse.IsStudent) assert.Equal(t, newTrainingDateAttendee.IsStudent, attendeeResponse.IsStudent)
assert.Equal(t, td.Price.Amount.String(), attendeeResponse.Bill.Amount) assert.Equal(t, td.PriceAmount.String(), attendeeResponse.Bill.Amount)
assert.Equal(t, td.Price.Currency, attendeeResponse.Bill.Currency) assert.Equal(t, td.PriceCurrency, attendeeResponse.Bill.Currency)
assert.Equal(t, false, attendeeResponse.HasPaid) assert.Equal(t, false, attendeeResponse.HasPaid)
assert.Equal(t, false, attendeeResponse.HasAttended) assert.Equal(t, false, attendeeResponse.HasAttended)
}) })
@ -758,17 +740,15 @@ func TestServer(t *testing.T) {
date := time.Date(2024, time.May, 1, 9, 0, 0, 0, time.UTC) date := time.Date(2024, time.May, 1, 9, 0, 0, 0, time.UTC)
td := &training.TrainingDate{ td := &training.TrainingDate{
Address: "Test Address 123, NYC", Address: "Test Address 123, NYC",
Capacity: 12, Capacity: 12,
Date: date, Date: date,
Days: tr.Days, Days: tr.Days,
IsOnline: false, IsOnline: false,
Location: "NYC", Location: "NYC",
StartTime: date, StartTime: date,
Price: money.Money{ PriceAmount: decimal.NewFromInt(200),
Amount: decimal.NewFromInt(200), PriceCurrency: "EUR",
Currency: "EUR",
},
} }
_ = handlers.trainingDateRepository.Create(tr.ID, td) _ = handlers.trainingDateRepository.Create(tr.ID, td)
@ -776,24 +756,22 @@ func TestServer(t *testing.T) {
attendees := make([]training.TrainingDateAttendee, attendeeCount) attendees := make([]training.TrainingDateAttendee, attendeeCount)
for i := range attendeeCount { for i := range attendeeCount {
nAtd := &training.TrainingDateAttendee{ nAtd := &training.TrainingDateAttendee{
Name: "John Doe", Name: "John Doe",
Email: "john.doe@example.com", Email: "john.doe@example.com",
Company: "Acme Inc.", Company: "Acme Inc.",
Position: "Software Engineer", Position: "Software Engineer",
Phone: "+420 123 456 789", Phone: "+420 123 456 789",
IsStudent: false, IsStudent: false,
Bill: money.Money{ BillAmount: td.PriceAmount,
Amount: td.Price.Amount, BillCurrency: td.PriceCurrency,
Currency: td.Price.Currency, HasPaid: false,
}, HasAttended: false,
HasPaid: false,
HasAttended: false,
} }
_ = handlers.trainingDateAttendeeRepository.Create(td.ID, nAtd) _ = handlers.trainingDateAttendeeRepository.Create(td.ID, nAtd)
attendees[i] = *nAtd attendees[i] = *nAtd
} }
rr, _ := doGet(t, app, "/v1/trainings/"+tr.ID.String()+"/dates/"+td.ID.String()+"/attendees") rr, _ := doGet(t, app, fmt.Sprintf("/v1/trainings/%d/dates/%d/attendees", tr.ID, td.ID))
assert.Equal(t, http.StatusOK, rr.StatusCode) assert.Equal(t, http.StatusOK, rr.StatusCode)
var attendeesResponse ListTrainingDateAttendeesResponse var attendeesResponse ListTrainingDateAttendeesResponse
@ -809,8 +787,8 @@ func TestServer(t *testing.T) {
assert.Equal(t, attendees[i].Position, attendee.Position) assert.Equal(t, attendees[i].Position, attendee.Position)
assert.Equal(t, attendees[i].IsStudent, *attendee.IsStudent) assert.Equal(t, attendees[i].IsStudent, *attendee.IsStudent)
assert.Equal(t, attendees[i].Phone, attendee.Phone) assert.Equal(t, attendees[i].Phone, attendee.Phone)
assert.Equal(t, attendees[i].Bill.Amount.String(), attendee.Bill.Amount) assert.Equal(t, attendees[i].BillAmount.String(), attendee.Bill.Amount)
assert.Equal(t, attendees[i].Bill.Currency, attendee.Bill.Currency) assert.Equal(t, attendees[i].BillCurrency, attendee.Bill.Currency)
assert.Equal(t, attendees[i].HasPaid, attendee.HasPaid) assert.Equal(t, attendees[i].HasPaid, attendee.HasPaid)
assert.Equal(t, attendees[i].HasAttended, attendee.HasAttended) assert.Equal(t, attendees[i].HasAttended, attendee.HasAttended)
} }
@ -835,38 +813,34 @@ func TestServer(t *testing.T) {
date := time.Date(2024, time.May, 1, 9, 0, 0, 0, time.UTC) date := time.Date(2024, time.May, 1, 9, 0, 0, 0, time.UTC)
td := &training.TrainingDate{ td := &training.TrainingDate{
Address: "Test Address 123, NYC", Address: "Test Address 123, NYC",
Capacity: 12, Capacity: 12,
Date: date, Date: date,
Days: tr.Days, Days: tr.Days,
IsOnline: false, IsOnline: false,
Location: "NYC", Location: "NYC",
StartTime: date, StartTime: date,
Price: money.Money{ PriceAmount: decimal.NewFromInt(200),
Amount: decimal.NewFromInt(200), PriceCurrency: "EUR",
Currency: "EUR",
},
} }
_ = handlers.trainingDateRepository.Create(tr.ID, td) _ = handlers.trainingDateRepository.Create(tr.ID, td)
attendee := &training.TrainingDateAttendee{ attendee := &training.TrainingDateAttendee{
Name: "John Doe", Name: "John Doe",
Email: "john.doe@example.com", Email: "john.doe@example.com",
Company: "Acme Inc.", Company: "Acme Inc.",
Position: "Software Engineer", Position: "Software Engineer",
Phone: "+420 123 456 789", Phone: "+420 123 456 789",
IsStudent: false, IsStudent: false,
Bill: money.Money{ BillAmount: td.PriceAmount,
Amount: td.Price.Amount, BillCurrency: td.PriceCurrency,
Currency: td.Price.Currency, HasPaid: false,
}, HasAttended: false,
HasPaid: false,
HasAttended: false,
} }
_ = handlers.trainingDateAttendeeRepository.Create(td.ID, attendee) _ = handlers.trainingDateAttendeeRepository.Create(td.ID, attendee)
rr, _ := doGet(t, app, "/v1/trainings/"+tr.ID.String()+"/dates/"+td.ID.String()+"/attendees/"+attendee.ID.String()) rr, _ := doGet(t, app, fmt.Sprintf("/v1/trainings/%d/dates/%d/attendees/%d", tr.ID, td.ID, attendee.ID))
var resultTrainingDateAttendee TrainingDateAttendee var resultTrainingDateAttendee TrainingDateAttendee
err := json.NewDecoder(rr.Body).Decode(&resultTrainingDateAttendee) err := json.NewDecoder(rr.Body).Decode(&resultTrainingDateAttendee)
@ -877,8 +851,8 @@ func TestServer(t *testing.T) {
assert.Equal(t, attendee.Position, resultTrainingDateAttendee.Position) assert.Equal(t, attendee.Position, resultTrainingDateAttendee.Position)
assert.Equal(t, attendee.IsStudent, *resultTrainingDateAttendee.IsStudent) assert.Equal(t, attendee.IsStudent, *resultTrainingDateAttendee.IsStudent)
assert.Equal(t, attendee.Phone, resultTrainingDateAttendee.Phone) assert.Equal(t, attendee.Phone, resultTrainingDateAttendee.Phone)
assert.Equal(t, attendee.Bill.Amount.String(), resultTrainingDateAttendee.Bill.Amount) assert.Equal(t, attendee.BillAmount.String(), resultTrainingDateAttendee.Bill.Amount)
assert.Equal(t, attendee.Bill.Currency, resultTrainingDateAttendee.Bill.Currency) assert.Equal(t, attendee.BillCurrency, resultTrainingDateAttendee.Bill.Currency)
assert.Equal(t, attendee.HasPaid, resultTrainingDateAttendee.HasPaid) assert.Equal(t, attendee.HasPaid, resultTrainingDateAttendee.HasPaid)
assert.Equal(t, attendee.HasAttended, resultTrainingDateAttendee.HasAttended) assert.Equal(t, attendee.HasAttended, resultTrainingDateAttendee.HasAttended)
}) })
@ -902,33 +876,29 @@ func TestServer(t *testing.T) {
date := time.Date(2024, time.May, 1, 9, 0, 0, 0, time.UTC) date := time.Date(2024, time.May, 1, 9, 0, 0, 0, time.UTC)
td := &training.TrainingDate{ td := &training.TrainingDate{
Address: "Test Address 123, NYC", Address: "Test Address 123, NYC",
Capacity: 12, Capacity: 12,
Date: date, Date: date,
Days: tr.Days, Days: tr.Days,
IsOnline: false, IsOnline: false,
Location: "NYC", Location: "NYC",
StartTime: date, StartTime: date,
Price: money.Money{ PriceAmount: decimal.NewFromInt(200),
Amount: decimal.NewFromInt(200), PriceCurrency: "EUR",
Currency: "EUR",
},
} }
_ = handlers.trainingDateRepository.Create(tr.ID, td) _ = handlers.trainingDateRepository.Create(tr.ID, td)
attendee := &training.TrainingDateAttendee{ attendee := &training.TrainingDateAttendee{
Name: "John Doe", Name: "John Doe",
Email: "john.doe@example.com", Email: "john.doe@example.com",
Company: "Acme Inc.", Company: "Acme Inc.",
Position: "Software Engineer", Position: "Software Engineer",
Phone: "+420 123 456 789", Phone: "+420 123 456 789",
IsStudent: false, IsStudent: false,
Bill: money.Money{ BillAmount: td.PriceAmount,
Amount: td.Price.Amount, BillCurrency: td.PriceCurrency,
Currency: td.Price.Currency, HasPaid: false,
}, HasAttended: false,
HasPaid: false,
HasAttended: false,
} }
_ = handlers.trainingDateAttendeeRepository.Create(td.ID, attendee) _ = handlers.trainingDateAttendeeRepository.Create(td.ID, attendee)
@ -942,7 +912,7 @@ func TestServer(t *testing.T) {
IsStudent: new(bool), IsStudent: new(bool),
} }
rr, _ := doPut(t, app, "/v1/trainings/"+tr.ID.String()+"/dates/"+td.ID.String()+"/attendees/"+attendee.ID.String(), newTrainingDateAttendee) rr, _ := doPut(t, app, fmt.Sprintf("/v1/trainings/%d/dates/%d/attendees/%d", tr.ID, td.ID, attendee.ID), newTrainingDateAttendee)
assert.Equal(t, http.StatusOK, rr.StatusCode) assert.Equal(t, http.StatusOK, rr.StatusCode)
var attendeeResponse UpdateTrainingDateAttendeeResponse var attendeeResponse UpdateTrainingDateAttendeeResponse
@ -954,8 +924,8 @@ func TestServer(t *testing.T) {
assert.Equal(t, newTrainingDateAttendee.Position, attendeeResponse.Position) assert.Equal(t, newTrainingDateAttendee.Position, attendeeResponse.Position)
assert.Equal(t, newTrainingDateAttendee.Phone, attendeeResponse.Phone) assert.Equal(t, newTrainingDateAttendee.Phone, attendeeResponse.Phone)
assert.Equal(t, newTrainingDateAttendee.IsStudent, attendeeResponse.IsStudent) assert.Equal(t, newTrainingDateAttendee.IsStudent, attendeeResponse.IsStudent)
assert.Equal(t, td.Price.Amount.String(), attendeeResponse.Bill.Amount) assert.Equal(t, td.PriceAmount.String(), attendeeResponse.Bill.Amount)
assert.Equal(t, td.Price.Currency, attendeeResponse.Bill.Currency) assert.Equal(t, td.PriceCurrency, attendeeResponse.Bill.Currency)
assert.Equal(t, attendee.HasPaid, attendeeResponse.HasPaid) assert.Equal(t, attendee.HasPaid, attendeeResponse.HasPaid)
assert.Equal(t, attendee.HasAttended, attendeeResponse.HasAttended) assert.Equal(t, attendee.HasAttended, attendeeResponse.HasAttended)
}) })
@ -979,44 +949,40 @@ func TestServer(t *testing.T) {
date := time.Date(2024, time.May, 1, 9, 0, 0, 0, time.UTC) date := time.Date(2024, time.May, 1, 9, 0, 0, 0, time.UTC)
td := &training.TrainingDate{ td := &training.TrainingDate{
Address: "Test Address 123, NYC", Address: "Test Address 123, NYC",
Capacity: 12, Capacity: 12,
Date: date, Date: date,
Days: tr.Days, Days: tr.Days,
IsOnline: false, IsOnline: false,
Location: "NYC", Location: "NYC",
StartTime: date, StartTime: date,
Price: money.Money{ PriceAmount: decimal.NewFromInt(200),
Amount: decimal.NewFromInt(200), PriceCurrency: "EUR",
Currency: "EUR",
},
} }
_ = handlers.trainingDateRepository.Create(tr.ID, td) _ = handlers.trainingDateRepository.Create(tr.ID, td)
attendee := &training.TrainingDateAttendee{ attendee := &training.TrainingDateAttendee{
Name: "John Doe", Name: "John Doe",
Email: "john.doe@example.com", Email: "john.doe@example.com",
Company: "Acme Inc.", Company: "Acme Inc.",
Position: "Software Engineer", Position: "Software Engineer",
Phone: "+420 123 456 789", Phone: "+420 123 456 789",
IsStudent: false, IsStudent: false,
Bill: money.Money{ BillAmount: td.PriceAmount,
Amount: td.Price.Amount, BillCurrency: td.PriceCurrency,
Currency: td.Price.Currency, HasPaid: false,
}, HasAttended: false,
HasPaid: false,
HasAttended: false,
} }
_ = handlers.trainingDateAttendeeRepository.Create(td.ID, attendee) _ = handlers.trainingDateAttendeeRepository.Create(td.ID, attendee)
rr, _ := doGet(t, app, "/v1/trainings/"+tr.ID.String()+"/dates/"+td.ID.String()+"/attendees/"+attendee.ID.String()) rr, _ := doGet(t, app, fmt.Sprintf("/v1/trainings/%d/dates/%d/attendees/%d", tr.ID, td.ID, attendee.ID))
assert.Equal(t, http.StatusOK, rr.StatusCode) assert.Equal(t, http.StatusOK, rr.StatusCode)
rr, _ = doDelete(t, app, "/v1/trainings/"+tr.ID.String()+"/dates/"+td.ID.String()+"/attendees/"+attendee.ID.String()) rr, _ = doDelete(t, app, fmt.Sprintf("/v1/trainings/%d/dates/%d/attendees/%d", tr.ID, td.ID, attendee.ID))
assert.Equal(t, http.StatusNoContent, rr.StatusCode) assert.Equal(t, http.StatusNoContent, rr.StatusCode)
rr, _ = doGet(t, app, "/v1/trainings/"+tr.ID.String()+"/dates/"+td.ID.String()+"/attendees/"+attendee.ID.String()) rr, _ = doGet(t, app, fmt.Sprintf("/v1/trainings/%d/dates/%d/attendees/%d", tr.ID, td.ID, attendee.ID))
assert.Equal(t, http.StatusNotFound, rr.StatusCode) assert.Equal(t, http.StatusNotFound, rr.StatusCode)
}) })
@ -1039,17 +1005,15 @@ func TestServer(t *testing.T) {
date := time.Date(2024, time.May, 1, 9, 0, 0, 0, time.UTC) date := time.Date(2024, time.May, 1, 9, 0, 0, 0, time.UTC)
td := &training.TrainingDate{ td := &training.TrainingDate{
Address: "Test Address 123, NYC", Address: "Test Address 123, NYC",
Capacity: 12, Capacity: 12,
Date: date, Date: date,
Days: tr.Days, Days: tr.Days,
IsOnline: false, IsOnline: false,
Location: "NYC", Location: "NYC",
StartTime: date, StartTime: date,
Price: money.Money{ PriceAmount: decimal.NewFromInt(200),
Amount: decimal.NewFromInt(200), PriceCurrency: "EUR",
Currency: "EUR",
},
} }
_ = handlers.trainingDateRepository.Create(tr.ID, td) _ = handlers.trainingDateRepository.Create(tr.ID, td)
@ -1058,23 +1022,21 @@ func TestServer(t *testing.T) {
} }
attendee := &training.TrainingDateAttendee{ attendee := &training.TrainingDateAttendee{
Name: "John Doe", Name: "John Doe",
Email: "john.doe@example.com", Email: "john.doe@example.com",
Company: "Acme Inc.", Company: "Acme Inc.",
Position: "Software Engineer", Position: "Software Engineer",
Phone: "+420 123 456 789", Phone: "+420 123 456 789",
IsStudent: false, IsStudent: false,
Bill: money.Money{ BillAmount: td.PriceAmount,
Amount: td.Price.Amount, BillCurrency: td.PriceCurrency,
Currency: td.Price.Currency, HasPaid: !paid.Paid,
}, HasAttended: false,
HasPaid: !paid.Paid,
HasAttended: false,
} }
_ = handlers.trainingDateAttendeeRepository.Create(td.ID, attendee) _ = handlers.trainingDateAttendeeRepository.Create(td.ID, attendee)
rr, _ := doGet(t, app, "/v1/trainings/"+tr.ID.String()+"/dates/"+td.ID.String()+"/attendees/"+attendee.ID.String()) rr, _ := doGet(t, app, fmt.Sprintf("/v1/trainings/%d/dates/%d/attendees/%d", tr.ID, td.ID, attendee.ID))
assert.Equal(t, http.StatusOK, rr.StatusCode) assert.Equal(t, http.StatusOK, rr.StatusCode)
var attendeeResponse TrainingDateAttendee var attendeeResponse TrainingDateAttendee
@ -1082,14 +1044,14 @@ func TestServer(t *testing.T) {
assert.NoError(t, err, "error unmarshalling response") assert.NoError(t, err, "error unmarshalling response")
assert.Equal(t, !paid.Paid, attendeeResponse.HasPaid) assert.Equal(t, !paid.Paid, attendeeResponse.HasPaid)
rr, _ = doPut(t, app, "/v1/trainings/"+tr.ID.String()+"/dates/"+td.ID.String()+"/attendees/"+attendee.ID.String()+"/paid", paid) rr, _ = doPut(t, app, fmt.Sprintf("/v1/trainings/%d/dates/%d/attendees/%d/paid", tr.ID, td.ID, attendee.ID), paid)
assert.Equal(t, http.StatusOK, rr.StatusCode) assert.Equal(t, http.StatusOK, rr.StatusCode)
err = json.NewDecoder(rr.Body).Decode(&attendeeResponse) err = json.NewDecoder(rr.Body).Decode(&attendeeResponse)
assert.NoError(t, err, "error unmarshalling response") assert.NoError(t, err, "error unmarshalling response")
assert.Equal(t, paid.Paid, attendeeResponse.HasPaid) assert.Equal(t, paid.Paid, attendeeResponse.HasPaid)
rr, _ = doGet(t, app, "/v1/trainings/"+tr.ID.String()+"/dates/"+td.ID.String()+"/attendees/"+attendee.ID.String()) rr, _ = doGet(t, app, fmt.Sprintf("/v1/trainings/%d/dates/%d/attendees/%d", tr.ID, td.ID, attendee.ID))
assert.Equal(t, http.StatusOK, rr.StatusCode) assert.Equal(t, http.StatusOK, rr.StatusCode)
err = json.NewDecoder(rr.Body).Decode(&attendeeResponse) err = json.NewDecoder(rr.Body).Decode(&attendeeResponse)
@ -1116,17 +1078,15 @@ func TestServer(t *testing.T) {
date := time.Date(2024, time.May, 1, 9, 0, 0, 0, time.UTC) date := time.Date(2024, time.May, 1, 9, 0, 0, 0, time.UTC)
td := &training.TrainingDate{ td := &training.TrainingDate{
Address: "Test Address 123, NYC", Address: "Test Address 123, NYC",
Capacity: 12, Capacity: 12,
Date: date, Date: date,
Days: tr.Days, Days: tr.Days,
IsOnline: false, IsOnline: false,
Location: "NYC", Location: "NYC",
StartTime: date, StartTime: date,
Price: money.Money{ PriceAmount: decimal.NewFromInt(200),
Amount: decimal.NewFromInt(200), PriceCurrency: "EUR",
Currency: "EUR",
},
} }
_ = handlers.trainingDateRepository.Create(tr.ID, td) _ = handlers.trainingDateRepository.Create(tr.ID, td)
@ -1135,23 +1095,21 @@ func TestServer(t *testing.T) {
} }
attendee := &training.TrainingDateAttendee{ attendee := &training.TrainingDateAttendee{
Name: "John Doe", Name: "John Doe",
Email: "john.doe@example.com", Email: "john.doe@example.com",
Company: "Acme Inc.", Company: "Acme Inc.",
Position: "Software Engineer", Position: "Software Engineer",
Phone: "+420 123 456 789", Phone: "+420 123 456 789",
IsStudent: false, IsStudent: false,
Bill: money.Money{ BillAmount: td.PriceAmount,
Amount: td.Price.Amount, BillCurrency: td.PriceCurrency,
Currency: td.Price.Currency, HasPaid: false,
}, HasAttended: !attended.Attended,
HasPaid: false,
HasAttended: !attended.Attended,
} }
_ = handlers.trainingDateAttendeeRepository.Create(td.ID, attendee) _ = handlers.trainingDateAttendeeRepository.Create(td.ID, attendee)
rr, _ := doGet(t, app, "/v1/trainings/"+tr.ID.String()+"/dates/"+td.ID.String()+"/attendees/"+attendee.ID.String()) rr, _ := doGet(t, app, fmt.Sprintf("/v1/trainings/%d/dates/%d/attendees/%d", tr.ID, td.ID, attendee.ID))
assert.Equal(t, http.StatusOK, rr.StatusCode) assert.Equal(t, http.StatusOK, rr.StatusCode)
var attendeeResponse TrainingDateAttendee var attendeeResponse TrainingDateAttendee
@ -1159,14 +1117,14 @@ func TestServer(t *testing.T) {
assert.NoError(t, err, "error unmarshalling response") assert.NoError(t, err, "error unmarshalling response")
assert.Equal(t, !attended.Attended, attendeeResponse.HasAttended) assert.Equal(t, !attended.Attended, attendeeResponse.HasAttended)
rr, _ = doPut(t, app, "/v1/trainings/"+tr.ID.String()+"/dates/"+td.ID.String()+"/attendees/"+attendee.ID.String()+"/attended", attended) rr, _ = doPut(t, app, fmt.Sprintf("/v1/trainings/%d/dates/%d/attendees/%d/attended", tr.ID, td.ID, attendee.ID), attended)
assert.Equal(t, http.StatusOK, rr.StatusCode) assert.Equal(t, http.StatusOK, rr.StatusCode)
err = json.NewDecoder(rr.Body).Decode(&attendeeResponse) err = json.NewDecoder(rr.Body).Decode(&attendeeResponse)
assert.NoError(t, err, "error unmarshalling response") assert.NoError(t, err, "error unmarshalling response")
assert.Equal(t, attended.Attended, attendeeResponse.HasAttended) assert.Equal(t, attended.Attended, attendeeResponse.HasAttended)
rr, _ = doGet(t, app, "/v1/trainings/"+tr.ID.String()+"/dates/"+td.ID.String()+"/attendees/"+attendee.ID.String()) rr, _ = doGet(t, app, fmt.Sprintf("/v1/trainings/%d/dates/%d/attendees/%d", tr.ID, td.ID, attendee.ID))
assert.Equal(t, http.StatusOK, rr.StatusCode) assert.Equal(t, http.StatusOK, rr.StatusCode)
err = json.NewDecoder(rr.Body).Decode(&attendeeResponse) err = json.NewDecoder(rr.Body).Decode(&attendeeResponse)
@ -1193,40 +1151,36 @@ func TestServer(t *testing.T) {
date := time.Date(2024, time.May, 1, 9, 0, 0, 0, time.UTC) date := time.Date(2024, time.May, 1, 9, 0, 0, 0, time.UTC)
td := &training.TrainingDate{ td := &training.TrainingDate{
Address: "Test Address 123, NYC", Address: "Test Address 123, NYC",
Capacity: 12, Capacity: 12,
Date: date, Date: date,
Days: tr.Days, Days: tr.Days,
IsOnline: false, IsOnline: false,
Location: "NYC", Location: "NYC",
StartTime: date, StartTime: date,
Price: money.Money{ PriceAmount: decimal.NewFromInt(200),
Amount: decimal.NewFromInt(200), PriceCurrency: "EUR",
Currency: "EUR",
},
} }
_ = handlers.trainingDateRepository.Create(tr.ID, td) _ = handlers.trainingDateRepository.Create(tr.ID, td)
attendeeCount := 9 attendeeCount := 9
for range attendeeCount { for range attendeeCount {
nAtd := &training.TrainingDateAttendee{ nAtd := &training.TrainingDateAttendee{
Name: "John Doe", Name: "John Doe",
Email: "john.doe@example.com", Email: "john.doe@example.com",
Company: "Acme Inc.", Company: "Acme Inc.",
Position: "Software Engineer", Position: "Software Engineer",
Phone: "+420 123 456 789", Phone: "+420 123 456 789",
IsStudent: false, IsStudent: false,
Bill: money.Money{ BillAmount: td.PriceAmount,
Amount: td.Price.Amount, BillCurrency: td.PriceCurrency,
Currency: td.Price.Currency, HasPaid: false,
}, HasAttended: false,
HasPaid: false,
HasAttended: false,
} }
_ = handlers.trainingDateAttendeeRepository.Create(td.ID, nAtd) _ = handlers.trainingDateAttendeeRepository.Create(td.ID, nAtd)
} }
rr, _ := doGet(t, app, "/v1/trainings/"+tr.ID.String()+"/dates/"+td.ID.String()+"/attendees/count") rr, _ := doGet(t, app, fmt.Sprintf("/v1/trainings/%d/dates/%d/attendees/count", tr.ID, td.ID))
assert.Equal(t, http.StatusOK, rr.StatusCode) assert.Equal(t, http.StatusOK, rr.StatusCode)
var attendeesResponse GetTrainingDateAttendeeCountResponse var attendeesResponse GetTrainingDateAttendeeCountResponse

View file

@ -3,14 +3,14 @@ BEGIN;
CREATE SCHEMA IF NOT EXISTS training; CREATE SCHEMA IF NOT EXISTS training;
CREATE TABLE IF NOT EXISTS training.trainings ( CREATE TABLE IF NOT EXISTS training.trainings (
id UUID PRIMARY KEY, id SERIAL PRIMARY KEY,
name varchar(255) NOT NULL, name varchar(255) NOT NULL,
description text NOT NULL, description text NOT NULL,
days smallint NOT NULL days smallint NOT NULL
); );
CREATE TABLE IF NOT EXISTS training.prices ( CREATE TABLE IF NOT EXISTS training.prices (
training_id UUID REFERENCES training.trainings(id), training_id SERIAL REFERENCES training.trainings(id),
amount NUMERIC(10,4) NOT NULL, amount NUMERIC(10,4) NOT NULL,
currency VARCHAR(3) NOT NULL, currency VARCHAR(3) NOT NULL,
CONSTRAINT positive_amount CHECK (amount >= 0), CONSTRAINT positive_amount CHECK (amount >= 0),
@ -21,8 +21,8 @@ CREATE TABLE IF NOT EXISTS training.prices (
); );
CREATE TABLE IF NOT EXISTS training.dates ( CREATE TABLE IF NOT EXISTS training.dates (
ID UUID PRIMARY KEY, ID SERIAL PRIMARY KEY,
training_id UUID REFERENCES training.trainings(id), training_id SERIAL REFERENCES training.trainings(id),
date DATE NOT NULL, date DATE NOT NULL,
start_time TIME NOT NULL, start_time TIME NOT NULL,
days SMALLINT NOT NULL, days SMALLINT NOT NULL,
@ -37,8 +37,8 @@ CREATE TABLE IF NOT EXISTS training.dates (
); );
CREATE TABLE IF NOT EXISTS training.date_attendees ( CREATE TABLE IF NOT EXISTS training.date_attendees (
id UUID PRIMARY KEY, id SERIAL PRIMARY KEY,
date_id UUID REFERENCES training.dates(id), date_id SERIAL REFERENCES training.dates(id),
name VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL,
email VARCHAR(255) NOT NULL, email VARCHAR(255) NOT NULL,
phone VARCHAR(20) NOT NULL, phone VARCHAR(20) NOT NULL,

View file

@ -8,11 +8,13 @@ import (
type InMemoryTrainingRepository struct { type InMemoryTrainingRepository struct {
trainings map[TrainingID]Training trainings map[TrainingID]Training
lock sync.RWMutex lock sync.RWMutex
ai int
} }
func NewInMemoryTrainingRepository() *InMemoryTrainingRepository { func NewInMemoryTrainingRepository() *InMemoryTrainingRepository {
return &InMemoryTrainingRepository{ return &InMemoryTrainingRepository{
trainings: make(map[TrainingID]Training), trainings: make(map[TrainingID]Training),
ai: 1,
} }
} }
@ -20,7 +22,8 @@ func (r *InMemoryTrainingRepository) Create(training *Training) error {
r.lock.Lock() r.lock.Lock()
defer r.lock.Unlock() defer r.lock.Unlock()
training.ID = NewTrainingID() training.ID = r.ai
r.ai++
r.trainings[training.ID] = *training r.trainings[training.ID] = *training
return nil return nil
} }
@ -73,12 +76,14 @@ type InMemoryTrainingDateRepository struct {
trainingToDates map[TrainingID][]TrainingDateID trainingToDates map[TrainingID][]TrainingDateID
lock sync.RWMutex lock sync.RWMutex
ai int
} }
func NewInMemoryTrainingDateRepository() *InMemoryTrainingDateRepository { func NewInMemoryTrainingDateRepository() *InMemoryTrainingDateRepository {
return &InMemoryTrainingDateRepository{ return &InMemoryTrainingDateRepository{
trainingDates: make(map[TrainingDateID]TrainingDate), trainingDates: make(map[TrainingDateID]TrainingDate),
trainingToDates: make(map[TrainingID][]TrainingDateID), trainingToDates: make(map[TrainingID][]TrainingDateID),
ai: 1,
} }
} }
@ -86,7 +91,8 @@ func (r *InMemoryTrainingDateRepository) Create(trainingID TrainingID, trainingD
r.lock.Lock() r.lock.Lock()
defer r.lock.Unlock() defer r.lock.Unlock()
trainingDate.ID = NewTrainingDateID() trainingDate.ID = r.ai
r.ai++
trainingDate.trainingID = trainingID trainingDate.trainingID = trainingID
r.trainingDates[trainingDate.ID] = *trainingDate r.trainingDates[trainingDate.ID] = *trainingDate
@ -181,12 +187,14 @@ type InMemoryTrainingDateAttendeeRepository struct {
dateToAttendees map[TrainingDateID][]TrainingDateAttendeeID dateToAttendees map[TrainingDateID][]TrainingDateAttendeeID
lock sync.RWMutex lock sync.RWMutex
ai int
} }
func NewInMemoryTrainingDateAttendeeRepository() *InMemoryTrainingDateAttendeeRepository { func NewInMemoryTrainingDateAttendeeRepository() *InMemoryTrainingDateAttendeeRepository {
return &InMemoryTrainingDateAttendeeRepository{ return &InMemoryTrainingDateAttendeeRepository{
attendees: make(map[TrainingDateAttendeeID]TrainingDateAttendee), attendees: make(map[TrainingDateAttendeeID]TrainingDateAttendee),
dateToAttendees: make(map[TrainingDateID][]TrainingDateAttendeeID), dateToAttendees: make(map[TrainingDateID][]TrainingDateAttendeeID),
ai: 1,
} }
} }
@ -194,7 +202,8 @@ func (r *InMemoryTrainingDateAttendeeRepository) Create(trainingDateID TrainingD
r.lock.Lock() r.lock.Lock()
defer r.lock.Unlock() defer r.lock.Unlock()
attendee.ID = NewTrainingDateAttendeeID() attendee.ID = r.ai
r.ai++
attendee.trainingDateID = trainingDateID attendee.trainingDateID = trainingDateID
r.attendees[attendee.ID] = *attendee r.attendees[attendee.ID] = *attendee

View file

@ -4,15 +4,9 @@ import (
"github.com/shopspring/decimal" "github.com/shopspring/decimal"
"gitlab.mareshq.com/hq/yggdrasil/internal/money" "gitlab.mareshq.com/hq/yggdrasil/internal/money"
"time" "time"
"github.com/google/uuid"
) )
type TrainingID = uuid.UUID type TrainingID = int
func NewTrainingID() TrainingID {
return uuid.Must(uuid.NewV7())
}
type Training struct { type Training struct {
ID TrainingID ID TrainingID
@ -35,11 +29,7 @@ const (
CorporateTrainingPrice TrainingPriceType = "CORPORATE" CorporateTrainingPrice TrainingPriceType = "CORPORATE"
) )
type TrainingDateID = uuid.UUID type TrainingDateID = int
func NewTrainingDateID() TrainingDateID {
return uuid.Must(uuid.NewV7())
}
type TrainingDate struct { type TrainingDate struct {
trainingID TrainingID trainingID TrainingID
@ -56,11 +46,7 @@ type TrainingDate struct {
PriceCurrency money.Currency `db:"price_currency"` PriceCurrency money.Currency `db:"price_currency"`
} }
type TrainingDateAttendeeID = uuid.UUID type TrainingDateAttendeeID = int
func NewTrainingDateAttendeeID() TrainingDateAttendeeID {
return uuid.Must(uuid.NewV7())
}
type TrainingDateAttendee struct { type TrainingDateAttendee struct {
trainingDateID TrainingDateID trainingDateID TrainingDateID

View file

@ -19,20 +19,18 @@ func (r *PostgresTrainingRepository) Create(training *Training) error {
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel() defer cancel()
training.ID = NewTrainingID() tx, txErr := r.pg.Begin(ctx)
if txErr != nil {
tx, err := r.pg.Begin(ctx) return txErr
if err != nil {
return err
} }
_, err = tx.Exec(ctx, ` queryErr := tx.QueryRow(ctx, `
INSERT INTO training.trainings (id, name, description, days) INSERT INTO training.trainings (name, description, days)
VALUES ($1, $2, $3, $4) VALUES ($1, $2, $3)
`, training.ID, training.Name, training.Description, training.Days) RETURNING id
`, training.Name, training.Description, training.Days).Scan(&training.ID)
if err != nil { if queryErr != nil {
return err return queryErr
} }
queryBatch := &pgx.Batch{} queryBatch := &pgx.Batch{}
@ -44,6 +42,7 @@ func (r *PostgresTrainingRepository) Create(training *Training) error {
`, training.ID, price.Amount, price.Currency, price.Type) `, training.ID, price.Amount, price.Currency, price.Type)
} }
var err error
batch := tx.SendBatch(ctx, queryBatch) batch := tx.SendBatch(ctx, queryBatch)
defer func() { defer func() {
if e := batch.Close(); e != nil { if e := batch.Close(); e != nil {
@ -246,12 +245,9 @@ func (r *PostgresTrainingDateRepository) Create(trainingID TrainingID, trainingD
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel() defer cancel()
trainingDate.ID = NewTrainingDateID() err := r.pg.QueryRow(ctx, `
INSERT INTO training.dates (training_id, date, start_time, days, is_online, location, address, capacity, price_amount, price_currency)
_, err := r.pg.Exec(ctx, ` VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10) RETURNING id`,
INSERT INTO training.dates (id, training_id, date, start_time, days, is_online, location, address, capacity, price_amount, price_currency)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11)`,
trainingDate.ID,
trainingID, trainingID,
trainingDate.Date, trainingDate.Date,
trainingDate.StartTime, trainingDate.StartTime,
@ -262,7 +258,7 @@ func (r *PostgresTrainingDateRepository) Create(trainingID TrainingID, trainingD
trainingDate.Capacity, trainingDate.Capacity,
trainingDate.PriceAmount, trainingDate.PriceAmount,
trainingDate.PriceCurrency, trainingDate.PriceCurrency,
) ).Scan(&trainingDate.ID)
if err != nil { if err != nil {
return err return err
} }
@ -447,12 +443,12 @@ func (r *PostgresTrainingDateAttendeeRepository) Create(trainingDateID TrainingD
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel() defer cancel()
attendee.ID = NewTrainingDateAttendeeID() err := r.pg.QueryRow(ctx, `
INSERT INTO training.date_attendees (date_id, name, email, phone, company, position, is_student, has_paid, has_attended, bill_amount, bill_currency)
_, err := r.pg.Exec(ctx, ` VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)
INSERT INTO training.date_attendees (id, date_id, name, email, phone, company, position, is_student, has_paid, has_attended, bill_amount, bill_currency) RETURNING id
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11) `, trainingDateID, attendee.Name, attendee.Email, attendee.Phone, attendee.Company, attendee.Position, attendee.IsStudent, attendee.HasPaid, attendee.HasAttended, attendee.BillAmount, attendee.BillCurrency).
`, attendee.ID, trainingDateID, attendee.Name, attendee.Email, attendee.Phone, attendee.Company, attendee.Position, attendee.IsStudent, attendee.HasPaid, attendee.HasAttended, attendee.BillAmount, attendee.BillCurrency) Scan(&attendee.ID)
if err != nil { if err != nil {
return err return err
} }