feat(training): add Repository.FindBySlug() method
This commit is contained in:
parent
fe38dd6683
commit
e0594892d5
4 changed files with 84 additions and 8 deletions
|
|
@ -3,7 +3,8 @@ package training
|
|||
import "errors"
|
||||
|
||||
var (
|
||||
ErrTrainingNotFound = errors.New("training not found")
|
||||
ErrTrainingDateNotFound = errors.New("training date not found")
|
||||
ErrTrainingDateAttendeeNotFound = errors.New("training date attendee not found")
|
||||
ErrTrainingNotFound = errors.New("training not found")
|
||||
ErrTrainingDateNotFound = errors.New("training date not found")
|
||||
ErrTrainingDateAttendeeNotFound = errors.New("training date attendee not found")
|
||||
ErrTrainingWithSlugAlreadyExists = errors.New("training with slug already exists")
|
||||
)
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import (
|
|||
|
||||
type InMemoryTrainingRepository struct {
|
||||
trainings map[ID]Training
|
||||
slugToID map[string]ID
|
||||
lock sync.RWMutex
|
||||
ai int
|
||||
}
|
||||
|
|
@ -15,6 +16,7 @@ type InMemoryTrainingRepository struct {
|
|||
func NewInMemoryTrainingRepository() *InMemoryTrainingRepository {
|
||||
return &InMemoryTrainingRepository{
|
||||
trainings: make(map[ID]Training),
|
||||
slugToID: make(map[string]ID),
|
||||
ai: 1,
|
||||
}
|
||||
}
|
||||
|
|
@ -35,7 +37,12 @@ func (r *InMemoryTrainingRepository) Create(training *Training) error {
|
|||
}
|
||||
}
|
||||
|
||||
if _, ok := r.slugToID[training.Slug]; ok {
|
||||
return ErrTrainingWithSlugAlreadyExists
|
||||
}
|
||||
|
||||
r.trainings[training.ID] = *training
|
||||
r.slugToID[training.Slug] = training.ID
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
@ -50,6 +57,18 @@ func (r *InMemoryTrainingRepository) FindByID(id ID) (*Training, error) {
|
|||
return &training, nil
|
||||
}
|
||||
|
||||
func (r *InMemoryTrainingRepository) FindBySlug(slug string) (*Training, error) {
|
||||
r.lock.RLock()
|
||||
defer r.lock.RUnlock()
|
||||
|
||||
id, ok := r.slugToID[slug]
|
||||
if !ok {
|
||||
return nil, ErrTrainingNotFound
|
||||
}
|
||||
|
||||
return r.FindByID(id)
|
||||
}
|
||||
|
||||
func (r *InMemoryTrainingRepository) FindAll() ([]Training, error) {
|
||||
r.lock.RLock()
|
||||
defer r.lock.RUnlock()
|
||||
|
|
@ -74,7 +93,16 @@ func (r *InMemoryTrainingRepository) Update(training *Training) error {
|
|||
}
|
||||
}
|
||||
|
||||
if _, ok := r.slugToID[training.Slug]; ok {
|
||||
return ErrTrainingWithSlugAlreadyExists
|
||||
}
|
||||
|
||||
r.trainings[training.ID] = *training
|
||||
|
||||
if r.trainings[training.ID].Slug != training.Slug {
|
||||
delete(r.slugToID, r.trainings[training.ID].Slug)
|
||||
r.slugToID[training.Slug] = training.ID
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
@ -87,6 +115,7 @@ func (r *InMemoryTrainingRepository) Delete(id ID) error {
|
|||
return ErrTrainingNotFound
|
||||
}
|
||||
|
||||
delete(r.slugToID, r.trainings[id].Slug)
|
||||
delete(r.trainings, id)
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import (
|
|||
"context"
|
||||
"github.com/jackc/pgx/v5"
|
||||
"github.com/jackc/pgx/v5/pgxpool"
|
||||
"gitlab.mareshq.com/hq/yggdrasil/pkg/slug"
|
||||
slugpkg "gitlab.mareshq.com/hq/yggdrasil/pkg/slug"
|
||||
"time"
|
||||
)
|
||||
|
||||
|
|
@ -21,7 +21,7 @@ func (r *PostgresTrainingRepository) Create(training *Training) error {
|
|||
defer cancel()
|
||||
|
||||
if training.Slug == "" {
|
||||
training.Slug = slug.NewString(training.Name)
|
||||
training.Slug = slugpkg.NewString(training.Name)
|
||||
}
|
||||
|
||||
tx, txErr := r.pg.Begin(ctx)
|
||||
|
|
@ -77,7 +77,7 @@ func (r *PostgresTrainingRepository) FindByID(id ID) (*Training, error) {
|
|||
|
||||
var training Training
|
||||
err := r.pg.QueryRow(ctx, `
|
||||
SELECT id, name, description, days
|
||||
SELECT id, name, slug, description, days
|
||||
FROM training.trainings
|
||||
WHERE id = $1
|
||||
`, id).Scan(&training.ID, &training.Name, &training.Slug, &training.Description, &training.Days)
|
||||
|
|
@ -112,6 +112,51 @@ func (r *PostgresTrainingRepository) FindByID(id ID) (*Training, error) {
|
|||
return &training, nil
|
||||
}
|
||||
|
||||
func (r *PostgresTrainingRepository) FindBySlug(slug string) (*Training, error) {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
defer cancel()
|
||||
|
||||
if err := slugpkg.Validate(slug); err != nil {
|
||||
return nil, ErrTrainingNotFound
|
||||
}
|
||||
|
||||
var training Training
|
||||
err := r.pg.QueryRow(ctx, `
|
||||
SELECT id, name, slug, description, days
|
||||
FROM training.trainings
|
||||
WHERE slug = $1
|
||||
`, slug).Scan(&training.ID, &training.Name, &training.Slug, &training.Description, &training.Days)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
rows, err := r.pg.Query(ctx, `
|
||||
SELECT amount, currency, type
|
||||
FROM training.prices
|
||||
WHERE training_id = $1
|
||||
`, training.ID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
training.Pricing = make([]Price, 0)
|
||||
training.Pricing, err = pgx.CollectRows[Price](rows, func(row pgx.CollectableRow) (Price, error) {
|
||||
var price Price
|
||||
err := row.Scan(&price.Amount, &price.Currency, &price.Type)
|
||||
if err != nil {
|
||||
return Price{}, err
|
||||
}
|
||||
return price, nil
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &training, nil
|
||||
}
|
||||
|
||||
func (r *PostgresTrainingRepository) FindAll() ([]Training, error) {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
defer cancel()
|
||||
|
|
@ -157,9 +202,9 @@ func (r *PostgresTrainingRepository) Update(training *Training) error {
|
|||
defer cancel()
|
||||
|
||||
if training.Slug == "" {
|
||||
training.Slug = slug.NewString(training.Name)
|
||||
training.Slug = slugpkg.NewString(training.Name)
|
||||
} else {
|
||||
slugValidateErr := slug.Validate(training.Slug)
|
||||
slugValidateErr := slugpkg.Validate(training.Slug)
|
||||
if slugValidateErr != nil {
|
||||
return slugValidateErr
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package training
|
|||
type Repository interface {
|
||||
Create(training *Training) error
|
||||
FindByID(id ID) (*Training, error)
|
||||
FindBySlug(slug string) (*Training, error)
|
||||
FindAll() ([]Training, error)
|
||||
Update(training *Training) error
|
||||
Delete(id ID) error
|
||||
|
|
|
|||
Reference in a new issue