Files
Datarush/internal/achievements/repository/postgres/repository.go
T
2025-12-19 23:12:22 +04:00

146 lines
3.7 KiB
Go

package postgres
import (
"context"
"database/sql"
"time"
"github.com/jmoiron/sqlx"
"google.golang.org/protobuf/types/known/timestamppb"
pb "datarush/pkg/api/achievements"
)
type AchievementRepository struct {
db *sqlx.DB
}
func NewAchievementRepository(db *sqlx.DB) *AchievementRepository {
return &AchievementRepository{db: db}
}
func (r *AchievementRepository) CreateAchievement(ctx context.Context, achievement *pb.Achievement) (*pb.Achievement, error) {
query := `INSERT INTO achievements (name, description, icon_url)
VALUES ($1, $2, $3) RETURNING id`
var createdAchievement pb.Achievement
err := r.db.QueryRowContext(ctx, query, achievement.Name, achievement.Description, achievement.IconUrl).
Scan(&createdAchievement.Id)
if err != nil {
return nil, err
}
createdAchievement.Name = achievement.Name
createdAchievement.Description = achievement.Description
createdAchievement.IconUrl = achievement.IconUrl
return &createdAchievement, nil
}
func (r *AchievementRepository) GetAchievement(ctx context.Context, id string) (*pb.Achievement, error) {
query := `SELECT id, name, description, icon_url
FROM achievements WHERE id = $1`
var achievement pb.Achievement
err := r.db.QueryRowContext(ctx, query, id).
Scan(&achievement.Id, &achievement.Name, &achievement.Description, &achievement.IconUrl)
if err != nil {
if err == sql.ErrNoRows {
return nil, sql.ErrNoRows
}
return nil, err
}
return &achievement, nil
}
func (r *AchievementRepository) EditAchievement(ctx context.Context, achievement *pb.Achievement) (*pb.Achievement, error) {
query := `UPDATE achievements SET name = $1, description = $2, icon_url = $3, updated_at = NOW()
WHERE id = $4`
_, err := r.db.ExecContext(ctx, query, achievement.Name, achievement.Description, achievement.IconUrl, achievement.Id)
if err != nil {
return nil, err
}
return achievement, nil
}
func (r *AchievementRepository) DeleteAchievement(ctx context.Context, id string) error {
_, err := r.db.ExecContext(ctx, "DELETE FROM achievements WHERE id = $1", id)
return err
}
func (r *AchievementRepository) ListAchievements(ctx context.Context) ([]*pb.Achievement, error) {
query := `SELECT id, name, description, icon_url FROM achievements ORDER BY created_at DESC`
rows, err := r.db.QueryContext(ctx, query)
if err != nil {
return nil, err
}
defer rows.Close()
var achievements []*pb.Achievement
for rows.Next() {
var achievement pb.Achievement
err := rows.Scan(&achievement.Id, &achievement.Name, &achievement.Description, &achievement.IconUrl)
if err != nil {
return nil, err
}
achievements = append(achievements, &achievement)
}
if err = rows.Err(); err != nil {
return nil, err
}
return achievements, nil
}
func (r *AchievementRepository) GetUserAchievements(ctx context.Context, userID string) ([]*pb.AchievementUser, error) {
query := `SELECT a.id, a.name, a.description, a.icon_url, ua.received_at
FROM user_achievements ua
INNER JOIN achievements a ON ua.achievement_id = a.id
WHERE ua.user_id = $1
ORDER BY ua.received_at DESC`
rows, err := r.db.QueryContext(ctx, query, userID)
if err != nil {
return nil, err
}
defer rows.Close()
var userAchievements []*pb.AchievementUser
for rows.Next() {
var achievement pb.Achievement
var receivedAt time.Time
err := rows.Scan(
&achievement.Id,
&achievement.Name,
&achievement.Description,
&achievement.IconUrl,
&receivedAt,
)
if err != nil {
return nil, err
}
userAchievement := &pb.AchievementUser{
Achievement: &achievement,
ReceivedAt: timestamppb.New(receivedAt),
}
userAchievements = append(userAchievements, userAchievement)
}
if err = rows.Err(); err != nil {
return nil, err
}
return userAchievements, nil
}