package repository import ( "database/sql" "time" "aggios-app/backend/internal/domain" "github.com/google/uuid" "github.com/lib/pq" ) // PlanRepository handles database operations for plans type PlanRepository struct { db *sql.DB } // NewPlanRepository creates a new plan repository func NewPlanRepository(db *sql.DB) *PlanRepository { return &PlanRepository{db: db} } // Create creates a new plan func (r *PlanRepository) Create(plan *domain.Plan) error { query := ` INSERT INTO plans (id, name, slug, description, min_users, max_users, monthly_price, annual_price, features, differentiators, storage_gb, is_active, created_at, updated_at) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14) RETURNING id, created_at, updated_at ` now := time.Now() plan.ID = uuid.New() plan.CreatedAt = now plan.UpdatedAt = now features := pq.Array(plan.Features) differentiators := pq.Array(plan.Differentiators) return r.db.QueryRow( query, plan.ID, plan.Name, plan.Slug, plan.Description, plan.MinUsers, plan.MaxUsers, plan.MonthlyPrice, plan.AnnualPrice, features, differentiators, plan.StorageGB, plan.IsActive, plan.CreatedAt, plan.UpdatedAt, ).Scan(&plan.ID, &plan.CreatedAt, &plan.UpdatedAt) } // GetByID retrieves a plan by ID func (r *PlanRepository) GetByID(id uuid.UUID) (*domain.Plan, error) { query := ` SELECT id, name, slug, description, min_users, max_users, monthly_price, annual_price, features, differentiators, storage_gb, is_active, created_at, updated_at FROM plans WHERE id = $1 ` plan := &domain.Plan{} var features, differentiators pq.StringArray err := r.db.QueryRow(query, id).Scan( &plan.ID, &plan.Name, &plan.Slug, &plan.Description, &plan.MinUsers, &plan.MaxUsers, &plan.MonthlyPrice, &plan.AnnualPrice, &features, &differentiators, &plan.StorageGB, &plan.IsActive, &plan.CreatedAt, &plan.UpdatedAt, ) if err != nil { return nil, err } plan.Features = []string(features) plan.Differentiators = []string(differentiators) return plan, nil } // GetBySlug retrieves a plan by slug func (r *PlanRepository) GetBySlug(slug string) (*domain.Plan, error) { query := ` SELECT id, name, slug, description, min_users, max_users, monthly_price, annual_price, features, differentiators, storage_gb, is_active, created_at, updated_at FROM plans WHERE slug = $1 ` plan := &domain.Plan{} var features, differentiators pq.StringArray err := r.db.QueryRow(query, slug).Scan( &plan.ID, &plan.Name, &plan.Slug, &plan.Description, &plan.MinUsers, &plan.MaxUsers, &plan.MonthlyPrice, &plan.AnnualPrice, &features, &differentiators, &plan.StorageGB, &plan.IsActive, &plan.CreatedAt, &plan.UpdatedAt, ) if err != nil { return nil, err } plan.Features = []string(features) plan.Differentiators = []string(differentiators) return plan, nil } // ListAll retrieves all plans func (r *PlanRepository) ListAll() ([]*domain.Plan, error) { query := ` SELECT id, name, slug, description, min_users, max_users, monthly_price, annual_price, features, differentiators, storage_gb, is_active, created_at, updated_at FROM plans ORDER BY min_users ASC ` rows, err := r.db.Query(query) if err != nil { return nil, err } defer rows.Close() var plans []*domain.Plan for rows.Next() { plan := &domain.Plan{} var features, differentiators pq.StringArray err := rows.Scan( &plan.ID, &plan.Name, &plan.Slug, &plan.Description, &plan.MinUsers, &plan.MaxUsers, &plan.MonthlyPrice, &plan.AnnualPrice, &features, &differentiators, &plan.StorageGB, &plan.IsActive, &plan.CreatedAt, &plan.UpdatedAt, ) if err != nil { return nil, err } plan.Features = []string(features) plan.Differentiators = []string(differentiators) plans = append(plans, plan) } return plans, rows.Err() } // ListActive retrieves all active plans func (r *PlanRepository) ListActive() ([]*domain.Plan, error) { query := ` SELECT id, name, slug, description, min_users, max_users, monthly_price, annual_price, features, differentiators, storage_gb, is_active, created_at, updated_at FROM plans WHERE is_active = true ORDER BY min_users ASC ` rows, err := r.db.Query(query) if err != nil { return nil, err } defer rows.Close() var plans []*domain.Plan for rows.Next() { plan := &domain.Plan{} var features, differentiators pq.StringArray err := rows.Scan( &plan.ID, &plan.Name, &plan.Slug, &plan.Description, &plan.MinUsers, &plan.MaxUsers, &plan.MonthlyPrice, &plan.AnnualPrice, &features, &differentiators, &plan.StorageGB, &plan.IsActive, &plan.CreatedAt, &plan.UpdatedAt, ) if err != nil { return nil, err } plan.Features = []string(features) plan.Differentiators = []string(differentiators) plans = append(plans, plan) } return plans, rows.Err() } // Update updates a plan func (r *PlanRepository) Update(plan *domain.Plan) error { query := ` UPDATE plans SET name = $2, slug = $3, description = $4, min_users = $5, max_users = $6, monthly_price = $7, annual_price = $8, features = $9, differentiators = $10, storage_gb = $11, is_active = $12, updated_at = $13 WHERE id = $1 RETURNING updated_at ` plan.UpdatedAt = time.Now() features := pq.Array(plan.Features) differentiators := pq.Array(plan.Differentiators) return r.db.QueryRow( query, plan.ID, plan.Name, plan.Slug, plan.Description, plan.MinUsers, plan.MaxUsers, plan.MonthlyPrice, plan.AnnualPrice, features, differentiators, plan.StorageGB, plan.IsActive, plan.UpdatedAt, ).Scan(&plan.UpdatedAt) } // Delete deletes a plan func (r *PlanRepository) Delete(id uuid.UUID) error { query := `DELETE FROM plans WHERE id = $1` result, err := r.db.Exec(query, id) if err != nil { return err } rowsAffected, err := result.RowsAffected() if err != nil { return err } if rowsAffected == 0 { return sql.ErrNoRows } return nil }