138 lines
4.5 KiB
Go
138 lines
4.5 KiB
Go
package repository
|
|
|
|
import (
|
|
"context"
|
|
"sno/internal/models"
|
|
|
|
"github.com/jackc/pgx/v5/pgxpool"
|
|
)
|
|
|
|
// RewardRepository defines the interface for reward data operations.
|
|
type RewardRepository interface {
|
|
Create(ctx context.Context, reward *models.Reward) (*models.Reward, error)
|
|
GetAllActive(ctx context.Context) ([]models.Reward, error)
|
|
GetByID(ctx context.Context, id int) (*models.Reward, error)
|
|
UpdateStock(ctx context.Context, id int, quantity int) error
|
|
Update(ctx context.Context, id int, reward *models.Reward) (*models.Reward, error)
|
|
Delete(ctx context.Context, id int) error
|
|
}
|
|
|
|
// postgresRewardRepository implements the RewardRepository interface.
|
|
type postgresRewardRepository struct {
|
|
db *pgxpool.Pool
|
|
}
|
|
|
|
// NewRewardRepository creates a new instance of a reward repository.
|
|
func NewRewardRepository(db *pgxpool.Pool) RewardRepository {
|
|
return &postgresRewardRepository{db: db}
|
|
}
|
|
|
|
// Create inserts a new reward into the database.
|
|
func (r *postgresRewardRepository) Create(ctx context.Context, reward *models.Reward) (*models.Reward, error) {
|
|
query := `
|
|
INSERT INTO rewards (title, description, image_url, price_stars, delivery_type, instructions, stock, created_by)
|
|
VALUES ($1, $2, $3, $4, $5, $6, $7, $8)
|
|
RETURNING id, is_active, created_at
|
|
`
|
|
err := r.db.QueryRow(ctx, query,
|
|
reward.Title, reward.Description, reward.ImageURL, reward.PriceStars, reward.DeliveryType, reward.Instructions, reward.Stock, reward.CreatedBy,
|
|
).Scan(&reward.ID, &reward.IsActive, &reward.CreatedAt)
|
|
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return reward, nil
|
|
}
|
|
|
|
// GetAllActive retrieves all active rewards that are in stock.
|
|
func (r *postgresRewardRepository) GetAllActive(ctx context.Context) ([]models.Reward, error) {
|
|
query := `
|
|
SELECT id, title, description, image_url, price_stars, delivery_type, instructions, stock, is_active, created_at
|
|
FROM rewards
|
|
WHERE is_active = true AND (stock > 0 OR stock = -1) -- Using -1 for infinite stock
|
|
ORDER BY price_stars ASC
|
|
`
|
|
rows, err := r.db.Query(ctx, query)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
|
|
var rewards []models.Reward
|
|
for rows.Next() {
|
|
var p models.Reward
|
|
if err := rows.Scan(&p.ID, &p.Title, &p.Description, &p.ImageURL, &p.PriceStars, &p.DeliveryType, &p.Instructions, &p.Stock, &p.IsActive, &p.CreatedAt); err != nil {
|
|
return nil, err
|
|
}
|
|
rewards = append(rewards, p)
|
|
}
|
|
|
|
if err := rows.Err(); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if rewards == nil {
|
|
return []models.Reward{}, nil
|
|
}
|
|
|
|
return rewards, nil
|
|
}
|
|
|
|
// GetByID retrieves a single reward by its ID.
|
|
func (r *postgresRewardRepository) GetByID(ctx context.Context, id int) (*models.Reward, error) {
|
|
query := `
|
|
SELECT id, title, description, image_url, price_stars, delivery_type, instructions, stock, is_active, created_at, created_by
|
|
FROM rewards
|
|
WHERE id = $1
|
|
`
|
|
var p models.Reward
|
|
err := r.db.QueryRow(ctx, query, id).Scan(
|
|
&p.ID, &p.Title, &p.Description, &p.ImageURL, &p.PriceStars, &p.DeliveryType, &p.Instructions, &p.Stock, &p.IsActive, &p.CreatedAt, &p.CreatedBy,
|
|
)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &p, nil
|
|
}
|
|
|
|
// UpdateStock updates the stock for a given reward.
|
|
func (r *postgresRewardRepository) UpdateStock(ctx context.Context, id int, quantity int) error {
|
|
query := `UPDATE rewards SET stock = stock - $1 WHERE id = $2 AND stock != -1` // -1 is infinite stock
|
|
querier := getQuerier(ctx, r.db)
|
|
_, err := querier.Exec(ctx, query, quantity, id)
|
|
return err
|
|
}
|
|
|
|
// Update updates an existing reward
|
|
func (r *postgresRewardRepository) Update(ctx context.Context, id int, reward *models.Reward) (*models.Reward, error) {
|
|
query := `
|
|
UPDATE rewards
|
|
SET title = $2, description = $3, image_url = $4, price_stars = $5,
|
|
delivery_type = $6, instructions = $7, stock = $8, is_active = $9
|
|
WHERE id = $1
|
|
RETURNING id, title, description, image_url, price_stars, delivery_type, instructions, stock, is_active, created_at, created_by
|
|
`
|
|
|
|
var p models.Reward
|
|
err := r.db.QueryRow(ctx, query,
|
|
id, reward.Title, reward.Description, reward.ImageURL, reward.PriceStars,
|
|
reward.DeliveryType, reward.Instructions, reward.Stock, reward.IsActive,
|
|
).Scan(
|
|
&p.ID, &p.Title, &p.Description, &p.ImageURL, &p.PriceStars,
|
|
&p.DeliveryType, &p.Instructions, &p.Stock, &p.IsActive, &p.CreatedAt, &p.CreatedBy,
|
|
)
|
|
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &p, nil
|
|
}
|
|
|
|
// Delete deletes a reward
|
|
func (r *postgresRewardRepository) Delete(ctx context.Context, id int) error {
|
|
query := `DELETE FROM rewards WHERE id = $1`
|
|
_, err := r.db.Exec(ctx, query, id)
|
|
return err
|
|
} |