1
0
Fork 0

feat: add postgres repository for training

This commit is contained in:
Vojtěch Mareš 2024-06-23 10:35:38 +02:00
parent 8c277ef692
commit ff7e320481
Signed by: vojtech.mares
GPG key ID: C6827B976F17240D
19 changed files with 1277 additions and 414 deletions

View file

@ -0,0 +1,561 @@
package training
import (
"context"
"github.com/jackc/pgx/v5"
"github.com/jackc/pgx/v5/pgxpool"
"time"
)
type PostgresTrainingRepository struct {
pg *pgxpool.Pool
}
func NewPostgresTrainingRepository(pg *pgxpool.Pool) *PostgresTrainingRepository {
return &PostgresTrainingRepository{pg: pg}
}
func (r *PostgresTrainingRepository) Create(training *Training) error {
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
training.ID = NewTrainingID()
tx, err := r.pg.Begin(ctx)
if err != nil {
return err
}
_, err = tx.Exec(ctx, `
INSERT INTO training.trainings (id, name, description, days)
VALUES ($1, $2, $3, $4)
`, training.ID, training.Name, training.Description, training.Days)
if err != nil {
return err
}
queryBatch := &pgx.Batch{}
for _, price := range training.Pricing {
queryBatch.Queue(`
INSERT INTO training.prices (training_id, amount, currency, type)
VALUES ($1, $2, $3, $4)
`, training.ID, price.Amount, price.Currency, price.Type)
}
batch := tx.SendBatch(ctx, queryBatch)
defer func() {
if e := batch.Close(); e != nil {
err = e
}
if err != nil {
_ = tx.Rollback(ctx)
} else {
if e := tx.Commit(ctx); e != nil {
err = e
}
}
}()
_, err = batch.Exec()
if err != nil {
return err
}
return nil
}
func (r *PostgresTrainingRepository) FindByID(id TrainingID) (*Training, error) {
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
var training Training
err := r.pg.QueryRow(ctx, `
SELECT id, name, description, days
FROM training.trainings
WHERE id = $1
`, id).Scan(&training.ID, &training.Name, &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
`, id)
if err != nil {
return nil, err
}
defer rows.Close()
training.Pricing = make([]TrainingPrice, 0)
training.Pricing, err = pgx.CollectRows[TrainingPrice](rows, func(row pgx.CollectableRow) (TrainingPrice, error) {
var price TrainingPrice
err := row.Scan(&price.Amount, &price.Currency, &price.Type)
if err != nil {
return TrainingPrice{}, 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()
rows, err := r.pg.Query(ctx, `
SELECT *
FROM training.trainings
`)
if err != nil {
return nil, err
}
defer rows.Close()
trainings, err := pgx.CollectRows(rows, func(row pgx.CollectableRow) (Training, error) {
var training Training
scanErr := row.Scan(&training.ID, &training.Name, &training.Description, &training.Days)
if scanErr != nil {
return Training{}, scanErr
}
priceRows, queryErr := r.pg.Query(ctx, `SELECT amount, currency, type FROM training.prices WHERE training_id = $1`, training.ID)
if queryErr != nil {
return Training{}, queryErr
}
training.Pricing, scanErr = pgx.CollectRows(priceRows, pgx.RowToStructByName[TrainingPrice])
if scanErr != nil {
return Training{}, scanErr
}
return training, nil
})
if err != nil {
return nil, err
}
return trainings, nil
}
func (r *PostgresTrainingRepository) Update(training *Training) error {
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
tx, err := r.pg.Begin(ctx)
if err != nil {
return err
}
_, err = tx.Exec(ctx, `
UPDATE training.trainings
SET name = $1, description = $2, days = $3
WHERE id = $4
`, training.Name, training.Description, training.Days, training.ID)
if err != nil {
return err
}
queryBatch := &pgx.Batch{}
for _, price := range training.Pricing {
queryBatch.Queue(`
INSERT INTO training.prices (training_id, amount, currency, type)
VALUES ($1, $2, $3, $4)
`, training.ID, price.Amount, price.Currency, price.Type)
}
batch := tx.SendBatch(ctx, queryBatch)
defer func() {
if e := batch.Close(); e != nil {
err = e
}
if err != nil {
_ = tx.Rollback(ctx)
} else {
if e := tx.Commit(ctx); e != nil {
err = e
}
}
}()
_, err = batch.Exec()
if err != nil {
return err
}
return nil
}
func (r *PostgresTrainingRepository) Delete(id TrainingID) error {
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
tx, err := r.pg.Begin(ctx)
if err != nil {
return err
}
_, err = tx.Exec(context.Background(), `
DELETE FROM training.prices
WHERE training_id = $1
`, id)
if err != nil {
return err
}
_, err = tx.Exec(context.Background(), `
DELETE FROM training.trainings
WHERE id = $1
`, id)
if err != nil {
return err
}
err = tx.Commit(ctx)
if err != nil {
return err
}
return nil
}
type PostgresTrainingDateRepository struct {
pg *pgxpool.Pool
}
func NewPostgresTrainingDateRepository(pg *pgxpool.Pool) *PostgresTrainingDateRepository {
return &PostgresTrainingDateRepository{pg: pg}
}
func (r *PostgresTrainingDateRepository) Create(trainingID TrainingID, trainingDate *TrainingDate) error {
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
trainingDate.ID = NewTrainingDateID()
_, err := r.pg.Exec(ctx, `
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,
trainingDate.Date,
trainingDate.StartTime,
trainingDate.Days,
trainingDate.IsOnline,
trainingDate.Location,
trainingDate.Address,
trainingDate.Capacity,
trainingDate.PriceAmount,
trainingDate.PriceCurrency,
)
if err != nil {
return err
}
return nil
}
func (r *PostgresTrainingDateRepository) FindByID(id TrainingDateID) (*TrainingDate, error) {
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
var trainingDate TrainingDate
err := r.pg.QueryRow(ctx, `SELECT * FROM training.dates WHERE id = $1`, id).
Scan(
&trainingDate.ID,
&trainingDate.trainingID,
&trainingDate.Date,
&trainingDate.StartTime,
&trainingDate.Days,
&trainingDate.IsOnline,
&trainingDate.Location,
&trainingDate.Address,
&trainingDate.Capacity,
&trainingDate.PriceAmount,
&trainingDate.PriceCurrency,
)
if err != nil {
return nil, err
}
return &trainingDate, nil
}
func (r *PostgresTrainingDateRepository) FindAll() ([]TrainingDate, error) {
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
rows, err := r.pg.Query(ctx, `SELECT * FROM training.dates`)
if err != nil {
return nil, err
}
defer rows.Close()
var trainingDates []TrainingDate
for rows.Next() {
var trainingDate TrainingDate
err := rows.Scan(
&trainingDate.ID,
&trainingDate.trainingID,
&trainingDate.Date,
&trainingDate.StartTime,
&trainingDate.Days,
&trainingDate.IsOnline,
&trainingDate.Location,
&trainingDate.Address,
&trainingDate.Capacity,
&trainingDate.PriceAmount,
&trainingDate.PriceCurrency,
)
if err != nil {
return nil, err
}
trainingDates = append(trainingDates, trainingDate)
}
return trainingDates, nil
}
func (r *PostgresTrainingDateRepository) FindAllByTrainingID(trainingID TrainingID) ([]TrainingDate, error) {
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
rows, err := r.pg.Query(ctx, `SELECT * FROM training.dates WHERE training_id = $1`, trainingID)
if err != nil {
return nil, err
}
defer rows.Close()
var trainingDates []TrainingDate
for rows.Next() {
var trainingDate TrainingDate
err := rows.Scan(
&trainingDate.ID,
&trainingDate.trainingID,
&trainingDate.Date,
&trainingDate.StartTime,
&trainingDate.Days,
&trainingDate.IsOnline,
&trainingDate.Location,
&trainingDate.Address,
&trainingDate.Capacity,
&trainingDate.PriceAmount,
&trainingDate.PriceCurrency,
)
if err != nil {
return nil, err
}
trainingDates = append(trainingDates, trainingDate)
}
return trainingDates, nil
}
func (r *PostgresTrainingDateRepository) FindUpcomingByTrainingID(trainingID TrainingID) ([]TrainingDate, error) {
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
rows, err := r.pg.Query(ctx, `
SELECT * FROM training.dates
WHERE training_id = $1 AND date > $2
`, trainingID, time.Now())
if err != nil {
return nil, err
}
defer rows.Close()
var trainingDates []TrainingDate
for rows.Next() {
var trainingDate TrainingDate
err := rows.Scan(
&trainingDate.ID,
&trainingDate.trainingID,
&trainingDate.Date,
&trainingDate.StartTime,
&trainingDate.Days,
&trainingDate.IsOnline,
&trainingDate.Location,
&trainingDate.Address,
&trainingDate.Capacity,
&trainingDate.PriceAmount,
&trainingDate.PriceCurrency,
)
if err != nil {
return nil, err
}
trainingDates = append(trainingDates, trainingDate)
}
return trainingDates, nil
}
func (r *PostgresTrainingDateRepository) Update(trainingDate *TrainingDate) error {
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
_, err := r.pg.Exec(ctx, `
UPDATE training.dates
SET date = $1, start_time = $2, days = $3, is_online = $4, location = $5, address = $6, capacity = $7, price_amount = $8, price_currency = $9
WHERE id = $10
`, trainingDate.Date, trainingDate.StartTime, trainingDate.Days, trainingDate.IsOnline, trainingDate.Location, trainingDate.Address, trainingDate.Capacity, trainingDate.PriceAmount, trainingDate.PriceCurrency, trainingDate.ID)
if err != nil {
return err
}
return nil
}
func (r *PostgresTrainingDateRepository) Delete(id TrainingDateID) error {
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
_, err := r.pg.Exec(ctx, `DELETE FROM training.dates WHERE id = $1`, id)
if err != nil {
return err
}
return nil
}
type PostgresTrainingDateAttendeeRepository struct {
pg *pgxpool.Pool
}
func NewPostgresTrainingDateAttendeeRepository(pg *pgxpool.Pool) *PostgresTrainingDateAttendeeRepository {
return &PostgresTrainingDateAttendeeRepository{pg: pg}
}
func (r *PostgresTrainingDateAttendeeRepository) Create(trainingDateID TrainingDateID, attendee *TrainingDateAttendee) error {
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
attendee.ID = NewTrainingDateAttendeeID()
_, err := r.pg.Exec(ctx, `
INSERT INTO training.date_attendees (id, date_id, name, email, phone, company, position, is_student, has_paid, has_attended, bill_amount, bill_currency)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11)
`, attendee.ID, trainingDateID, attendee.Name, attendee.Email, attendee.Phone, attendee.Company, attendee.Position, attendee.IsStudent, attendee.HasPaid, attendee.HasAttended, attendee.BillAmount, attendee.BillCurrency)
if err != nil {
return err
}
return nil
}
func (r *PostgresTrainingDateAttendeeRepository) FindByID(id TrainingDateAttendeeID) (*TrainingDateAttendee, error) {
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
var attendee TrainingDateAttendee
err := r.pg.QueryRow(ctx, `
SELECT id, date_id, name, email, phone, company, position, is_student, has_paid, has_attended, bill_amount, bill_currency
FROM training.date_attendees
WHERE id = $1
`, id).Scan(&attendee.ID, &attendee.trainingDateID, &attendee.Name, &attendee.Email, &attendee.Phone, &attendee.Company, &attendee.Position, &attendee.IsStudent, &attendee.HasPaid, &attendee.HasAttended, &attendee.BillAmount, &attendee.BillCurrency)
if err != nil {
return nil, err
}
return &attendee, nil
}
func (r *PostgresTrainingDateAttendeeRepository) FindAll() ([]TrainingDateAttendee, error) {
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
rows, err := r.pg.Query(ctx, `
SELECT id, date_id, name, email, phone, company, position, is_student, has_paid, has_attended, bill_amount, bill_currency
FROM training.date_attendees
`)
if err != nil {
return nil, err
}
defer rows.Close()
var attendees []TrainingDateAttendee
for rows.Next() {
var attendee TrainingDateAttendee
err := rows.Scan(&attendee.ID, &attendee.trainingDateID, &attendee.Name, &attendee.Email, &attendee.Phone, &attendee.Company, &attendee.Position, &attendee.IsStudent, &attendee.HasPaid, &attendee.HasAttended, &attendee.BillAmount, &attendee.BillCurrency)
if err != nil {
return nil, err
}
attendees = append(attendees, attendee)
}
return attendees, nil
}
func (r *PostgresTrainingDateAttendeeRepository) FindAllByTrainingDateID(trainingDateID TrainingDateID) ([]TrainingDateAttendee, error) {
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
rows, err := r.pg.Query(ctx, `
SELECT id, date_id, name, email, phone, company, position, is_student, has_paid, has_attended, bill_amount, bill_currency
FROM training.date_attendees
WHERE date_id = $1
`, trainingDateID)
if err != nil {
return nil, err
}
defer rows.Close()
var attendees []TrainingDateAttendee
for rows.Next() {
var attendee TrainingDateAttendee
err := rows.Scan(&attendee.ID, &attendee.trainingDateID, &attendee.Name, &attendee.Email, &attendee.Phone, &attendee.Company, &attendee.Position, &attendee.IsStudent, &attendee.HasPaid, &attendee.HasAttended, &attendee.BillAmount, &attendee.BillCurrency)
if err != nil {
return nil, err
}
attendees = append(attendees, attendee)
}
return attendees, nil
}
func (r *PostgresTrainingDateAttendeeRepository) Update(attendee *TrainingDateAttendee) error {
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
_, err := r.pg.Exec(ctx, `
UPDATE training.date_attendees
SET name = $1, email = $2, phone = $3, company = $4, position = $5, is_student = $6, has_paid = $7, has_attended = $8, bill_amount = $9, bill_currency = $10
WHERE id = $10
`, attendee.Name, attendee.Email, attendee.Phone, attendee.Company, attendee.Position, attendee.IsStudent, attendee.HasPaid, attendee.HasAttended, attendee.BillAmount, attendee.BillCurrency, attendee.ID)
if err != nil {
return err
}
return nil
}
func (r *PostgresTrainingDateAttendeeRepository) Delete(id TrainingDateAttendeeID) error {
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
_, err := r.pg.Exec(ctx, `DELETE FROM training.date_attendees WHERE id = $1`, id)
if err != nil {
return err
}
return nil
}