package repository import ( "context" "fmt" "github.com/jackc/pgx/v5" "github.com/jackc/pgx/v5/pgxpool" "gogs.fxtmmsk.ru/foxtime/photoplaces/backend/internal/models" ) type SubscriptionRepo struct { pool *pgxpool.Pool } func NewSubscriptionRepo(pool *pgxpool.Pool) *SubscriptionRepo { return &SubscriptionRepo{pool: pool} } func (r *SubscriptionRepo) Create(ctx context.Context, s *models.Subscription) error { err := r.pool.QueryRow(ctx, `INSERT INTO subscriptions (user_id, plan, status, current_period_start, current_period_end, provider_subscription_id) VALUES ($1, $2, $3, $4, $5, $6) RETURNING id, created_at, updated_at`, s.UserID, s.Plan, s.Status, s.PeriodStart, s.PeriodEnd, s.ProviderSubID, ).Scan(&s.ID, &s.CreatedAt, &s.UpdatedAt) if err != nil { return fmt.Errorf("create subscription: %w", err) } return nil } func (r *SubscriptionRepo) GetByID(ctx context.Context, id string) (*models.Subscription, error) { row := r.pool.QueryRow(ctx, `SELECT id, user_id, plan, status, current_period_start, current_period_end, provider_subscription_id, created_at, updated_at FROM subscriptions WHERE id = $1`, id) return scanSubscription(row) } func (r *SubscriptionRepo) GetActiveByUser(ctx context.Context, userID string) (*models.Subscription, error) { row := r.pool.QueryRow(ctx, `SELECT id, user_id, plan, status, current_period_start, current_period_end, provider_subscription_id, created_at, updated_at FROM subscriptions WHERE user_id = $1 AND status = 'active' ORDER BY created_at DESC LIMIT 1`, userID) return scanSubscription(row) } func (r *SubscriptionRepo) ListByUser(ctx context.Context, userID string) ([]*models.Subscription, error) { rows, err := r.pool.Query(ctx, `SELECT id, user_id, plan, status, current_period_start, current_period_end, provider_subscription_id, created_at, updated_at FROM subscriptions WHERE user_id = $1 ORDER BY created_at DESC`, userID) if err != nil { return nil, err } defer rows.Close() var subs []*models.Subscription for rows.Next() { s, err := scanSubscription(rows) if err != nil { return nil, err } subs = append(subs, s) } return subs, nil } func (r *SubscriptionRepo) UpdateStatus(ctx context.Context, id, status string) error { _, err := r.pool.Exec(ctx, `UPDATE subscriptions SET status=$1, updated_at=now() WHERE id=$2`, status, id) return err } func (r *SubscriptionRepo) Cancel(ctx context.Context, id string) error { _, err := r.pool.Exec(ctx, `UPDATE subscriptions SET status='cancelled', updated_at=now() WHERE id=$1 AND status='active'`, id) return err } func scanSubscription(row interface{ Scan(dest ...any) error }) (*models.Subscription, error) { var s models.Subscription err := row.Scan(&s.ID, &s.UserID, &s.Plan, &s.Status, &s.PeriodStart, &s.PeriodEnd, &s.ProviderSubID, &s.CreatedAt, &s.UpdatedAt) if err != nil { if err == pgx.ErrNoRows { return nil, nil } return nil, err } return &s, nil }