301 lines
6.5 KiB
Go
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
|
|
}
|