Files
aggios.app/backend/internal/repository/solution_repository.go
2025-12-17 13:36:23 -03:00

301 lines
6.5 KiB
Go

package repository
import (
"aggios-app/backend/internal/domain"
"database/sql"
"fmt"
)
type SolutionRepository struct {
db *sql.DB
}
func NewSolutionRepository(db *sql.DB) *SolutionRepository {
return &SolutionRepository{db: db}
}
// ==================== SOLUTIONS ====================
func (r *SolutionRepository) CreateSolution(solution *domain.Solution) error {
query := `
INSERT INTO solutions (id, name, slug, icon, description, is_active)
VALUES ($1, $2, $3, $4, $5, $6)
RETURNING created_at, updated_at
`
return r.db.QueryRow(
query,
solution.ID, solution.Name, solution.Slug, solution.Icon,
solution.Description, solution.IsActive,
).Scan(&solution.CreatedAt, &solution.UpdatedAt)
}
func (r *SolutionRepository) GetAllSolutions() ([]domain.Solution, error) {
query := `
SELECT id, name, slug, icon, description, is_active, created_at, updated_at
FROM solutions
ORDER BY created_at DESC
`
rows, err := r.db.Query(query)
if err != nil {
return nil, err
}
defer rows.Close()
var solutions []domain.Solution
for rows.Next() {
var s domain.Solution
err := rows.Scan(
&s.ID, &s.Name, &s.Slug, &s.Icon, &s.Description,
&s.IsActive, &s.CreatedAt, &s.UpdatedAt,
)
if err != nil {
return nil, err
}
solutions = append(solutions, s)
}
return solutions, nil
}
func (r *SolutionRepository) GetActiveSolutions() ([]domain.Solution, error) {
query := `
SELECT id, name, slug, icon, description, is_active, created_at, updated_at
FROM solutions
WHERE is_active = true
ORDER BY name
`
rows, err := r.db.Query(query)
if err != nil {
return nil, err
}
defer rows.Close()
var solutions []domain.Solution
for rows.Next() {
var s domain.Solution
err := rows.Scan(
&s.ID, &s.Name, &s.Slug, &s.Icon, &s.Description,
&s.IsActive, &s.CreatedAt, &s.UpdatedAt,
)
if err != nil {
return nil, err
}
solutions = append(solutions, s)
}
return solutions, nil
}
func (r *SolutionRepository) GetSolutionByID(id string) (*domain.Solution, error) {
query := `
SELECT id, name, slug, icon, description, is_active, created_at, updated_at
FROM solutions
WHERE id = $1
`
var s domain.Solution
err := r.db.QueryRow(query, id).Scan(
&s.ID, &s.Name, &s.Slug, &s.Icon, &s.Description,
&s.IsActive, &s.CreatedAt, &s.UpdatedAt,
)
if err != nil {
return nil, err
}
return &s, nil
}
func (r *SolutionRepository) GetSolutionBySlug(slug string) (*domain.Solution, error) {
query := `
SELECT id, name, slug, icon, description, is_active, created_at, updated_at
FROM solutions
WHERE slug = $1
`
var s domain.Solution
err := r.db.QueryRow(query, slug).Scan(
&s.ID, &s.Name, &s.Slug, &s.Icon, &s.Description,
&s.IsActive, &s.CreatedAt, &s.UpdatedAt,
)
if err != nil {
return nil, err
}
return &s, nil
}
func (r *SolutionRepository) UpdateSolution(solution *domain.Solution) error {
query := `
UPDATE solutions SET
name = $1, slug = $2, icon = $3, description = $4, is_active = $5, updated_at = CURRENT_TIMESTAMP
WHERE id = $6
`
result, err := r.db.Exec(
query,
solution.Name, solution.Slug, solution.Icon, solution.Description,
solution.IsActive, solution.ID,
)
if err != nil {
return err
}
rows, err := result.RowsAffected()
if err != nil {
return err
}
if rows == 0 {
return fmt.Errorf("solution not found")
}
return nil
}
func (r *SolutionRepository) DeleteSolution(id string) error {
query := `DELETE FROM solutions WHERE id = $1`
result, err := r.db.Exec(query, id)
if err != nil {
return err
}
rows, err := result.RowsAffected()
if err != nil {
return err
}
if rows == 0 {
return fmt.Errorf("solution not found")
}
return nil
}
// ==================== PLAN <-> SOLUTION ====================
func (r *SolutionRepository) AddSolutionToPlan(planID, solutionID string) error {
query := `
INSERT INTO plan_solutions (plan_id, solution_id)
VALUES ($1, $2)
ON CONFLICT (plan_id, solution_id) DO NOTHING
`
_, err := r.db.Exec(query, planID, solutionID)
return err
}
func (r *SolutionRepository) RemoveSolutionFromPlan(planID, solutionID string) error {
query := `DELETE FROM plan_solutions WHERE plan_id = $1 AND solution_id = $2`
_, err := r.db.Exec(query, planID, solutionID)
return err
}
func (r *SolutionRepository) GetPlanSolutions(planID string) ([]domain.Solution, error) {
query := `
SELECT s.id, s.name, s.slug, s.icon, s.description, s.is_active, s.created_at, s.updated_at
FROM solutions s
INNER JOIN plan_solutions ps ON s.id = ps.solution_id
WHERE ps.plan_id = $1
ORDER BY s.name
`
rows, err := r.db.Query(query, planID)
if err != nil {
return nil, err
}
defer rows.Close()
var solutions []domain.Solution
for rows.Next() {
var s domain.Solution
err := rows.Scan(
&s.ID, &s.Name, &s.Slug, &s.Icon, &s.Description,
&s.IsActive, &s.CreatedAt, &s.UpdatedAt,
)
if err != nil {
return nil, err
}
solutions = append(solutions, s)
}
return solutions, nil
}
func (r *SolutionRepository) SetPlanSolutions(planID string, solutionIDs []string) error {
// Inicia transação
tx, err := r.db.Begin()
if err != nil {
return err
}
// Remove todas as soluções antigas do plano
_, err = tx.Exec(`DELETE FROM plan_solutions WHERE plan_id = $1`, planID)
if err != nil {
tx.Rollback()
return err
}
// Adiciona as novas soluções
stmt, err := tx.Prepare(`INSERT INTO plan_solutions (plan_id, solution_id) VALUES ($1, $2)`)
if err != nil {
tx.Rollback()
return err
}
defer stmt.Close()
for _, solutionID := range solutionIDs {
_, err = stmt.Exec(planID, solutionID)
if err != nil {
tx.Rollback()
return err
}
}
return tx.Commit()
}
func (r *SolutionRepository) GetTenantSolutions(tenantID string) ([]domain.Solution, error) {
query := `
SELECT DISTINCT s.id, s.name, s.slug, s.icon, s.description, s.is_active, s.created_at, s.updated_at
FROM solutions s
INNER JOIN plan_solutions ps ON s.id = ps.solution_id
INNER JOIN agency_subscriptions asub ON ps.plan_id = asub.plan_id
WHERE asub.agency_id = $1 AND s.is_active = true AND asub.status = 'active'
ORDER BY s.name
`
rows, err := r.db.Query(query, tenantID)
if err != nil {
return nil, err
}
defer rows.Close()
var solutions []domain.Solution
for rows.Next() {
var s domain.Solution
err := rows.Scan(
&s.ID, &s.Name, &s.Slug, &s.Icon, &s.Description,
&s.IsActive, &s.CreatedAt, &s.UpdatedAt,
)
if err != nil {
return nil, err
}
solutions = append(solutions, s)
}
// Se não encontrou via subscription, retorna array vazio
if solutions == nil {
solutions = []domain.Solution{}
}
return solutions, nil
}