subscriptions.go 2.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. package repository
  2. import (
  3. "context"
  4. "fmt"
  5. "github.com/jackc/pgx/v5"
  6. "github.com/jackc/pgx/v5/pgxpool"
  7. "gogs.fxtmmsk.ru/foxtime/photoplaces/backend/internal/models"
  8. )
  9. type SubscriptionRepo struct {
  10. pool *pgxpool.Pool
  11. }
  12. func NewSubscriptionRepo(pool *pgxpool.Pool) *SubscriptionRepo {
  13. return &SubscriptionRepo{pool: pool}
  14. }
  15. func (r *SubscriptionRepo) Create(ctx context.Context, s *models.Subscription) error {
  16. err := r.pool.QueryRow(ctx,
  17. `INSERT INTO subscriptions (user_id, plan, status, current_period_start, current_period_end, provider_subscription_id)
  18. VALUES ($1, $2, $3, $4, $5, $6)
  19. RETURNING id, created_at, updated_at`,
  20. s.UserID, s.Plan, s.Status, s.PeriodStart, s.PeriodEnd, s.ProviderSubID,
  21. ).Scan(&s.ID, &s.CreatedAt, &s.UpdatedAt)
  22. if err != nil {
  23. return fmt.Errorf("create subscription: %w", err)
  24. }
  25. return nil
  26. }
  27. func (r *SubscriptionRepo) GetByID(ctx context.Context, id string) (*models.Subscription, error) {
  28. row := r.pool.QueryRow(ctx,
  29. `SELECT id, user_id, plan, status, current_period_start, current_period_end,
  30. provider_subscription_id, created_at, updated_at
  31. FROM subscriptions WHERE id = $1`, id)
  32. return scanSubscription(row)
  33. }
  34. func (r *SubscriptionRepo) GetActiveByUser(ctx context.Context, userID string) (*models.Subscription, error) {
  35. row := r.pool.QueryRow(ctx,
  36. `SELECT id, user_id, plan, status, current_period_start, current_period_end,
  37. provider_subscription_id, created_at, updated_at
  38. FROM subscriptions
  39. WHERE user_id = $1 AND status = 'active'
  40. ORDER BY created_at DESC LIMIT 1`, userID)
  41. return scanSubscription(row)
  42. }
  43. func (r *SubscriptionRepo) ListByUser(ctx context.Context, userID string) ([]*models.Subscription, error) {
  44. rows, err := r.pool.Query(ctx,
  45. `SELECT id, user_id, plan, status, current_period_start, current_period_end,
  46. provider_subscription_id, created_at, updated_at
  47. FROM subscriptions WHERE user_id = $1 ORDER BY created_at DESC`, userID)
  48. if err != nil {
  49. return nil, err
  50. }
  51. defer rows.Close()
  52. var subs []*models.Subscription
  53. for rows.Next() {
  54. s, err := scanSubscription(rows)
  55. if err != nil {
  56. return nil, err
  57. }
  58. subs = append(subs, s)
  59. }
  60. return subs, nil
  61. }
  62. func (r *SubscriptionRepo) UpdateStatus(ctx context.Context, id, status string) error {
  63. _, err := r.pool.Exec(ctx,
  64. `UPDATE subscriptions SET status=$1, updated_at=now() WHERE id=$2`, status, id)
  65. return err
  66. }
  67. func (r *SubscriptionRepo) Cancel(ctx context.Context, id string) error {
  68. _, err := r.pool.Exec(ctx,
  69. `UPDATE subscriptions SET status='cancelled', updated_at=now() WHERE id=$1 AND status='active'`, id)
  70. return err
  71. }
  72. func scanSubscription(row interface{ Scan(dest ...any) error }) (*models.Subscription, error) {
  73. var s models.Subscription
  74. err := row.Scan(&s.ID, &s.UserID, &s.Plan, &s.Status, &s.PeriodStart,
  75. &s.PeriodEnd, &s.ProviderSubID, &s.CreatedAt, &s.UpdatedAt)
  76. if err != nil {
  77. if err == pgx.ErrNoRows {
  78. return nil, nil
  79. }
  80. return nil, err
  81. }
  82. return &s, nil
  83. }