269 lines
5.5 KiB
Go
269 lines
5.5 KiB
Go
package repository
|
|
|
|
import (
|
|
"database/sql"
|
|
"time"
|
|
|
|
"aggios-app/backend/internal/domain"
|
|
|
|
"github.com/google/uuid"
|
|
)
|
|
|
|
// TenantRepository handles database operations for tenants
|
|
type TenantRepository struct {
|
|
db *sql.DB
|
|
}
|
|
|
|
// NewTenantRepository creates a new tenant repository
|
|
func NewTenantRepository(db *sql.DB) *TenantRepository {
|
|
return &TenantRepository{db: db}
|
|
}
|
|
|
|
// Create creates a new tenant
|
|
func (r *TenantRepository) Create(tenant *domain.Tenant) error {
|
|
query := `
|
|
INSERT INTO tenants (
|
|
id, name, domain, subdomain, cnpj, razao_social, email, website,
|
|
address, city, state, zip, description, industry, created_at, updated_at
|
|
)
|
|
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16)
|
|
RETURNING id, created_at, updated_at
|
|
`
|
|
|
|
now := time.Now()
|
|
tenant.ID = uuid.New()
|
|
tenant.CreatedAt = now
|
|
tenant.UpdatedAt = now
|
|
|
|
return r.db.QueryRow(
|
|
query,
|
|
tenant.ID,
|
|
tenant.Name,
|
|
tenant.Domain,
|
|
tenant.Subdomain,
|
|
tenant.CNPJ,
|
|
tenant.RazaoSocial,
|
|
tenant.Email,
|
|
tenant.Website,
|
|
tenant.Address,
|
|
tenant.City,
|
|
tenant.State,
|
|
tenant.Zip,
|
|
tenant.Description,
|
|
tenant.Industry,
|
|
tenant.CreatedAt,
|
|
tenant.UpdatedAt,
|
|
).Scan(&tenant.ID, &tenant.CreatedAt, &tenant.UpdatedAt)
|
|
}
|
|
|
|
// FindByID finds a tenant by ID
|
|
func (r *TenantRepository) FindByID(id uuid.UUID) (*domain.Tenant, error) {
|
|
query := `
|
|
SELECT id, name, domain, subdomain, cnpj, razao_social, email, phone, website,
|
|
address, city, state, zip, description, industry, is_active, created_at, updated_at
|
|
FROM tenants
|
|
WHERE id = $1
|
|
`
|
|
|
|
tenant := &domain.Tenant{}
|
|
var cnpj, razaoSocial, email, phone, website, address, city, state, zip, description, industry sql.NullString
|
|
|
|
err := r.db.QueryRow(query, id).Scan(
|
|
&tenant.ID,
|
|
&tenant.Name,
|
|
&tenant.Domain,
|
|
&tenant.Subdomain,
|
|
&cnpj,
|
|
&razaoSocial,
|
|
&email,
|
|
&phone,
|
|
&website,
|
|
&address,
|
|
&city,
|
|
&state,
|
|
&zip,
|
|
&description,
|
|
&industry,
|
|
&tenant.IsActive,
|
|
&tenant.CreatedAt,
|
|
&tenant.UpdatedAt,
|
|
)
|
|
|
|
if err == sql.ErrNoRows {
|
|
return nil, nil
|
|
}
|
|
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// Handle nullable fields
|
|
if cnpj.Valid {
|
|
tenant.CNPJ = cnpj.String
|
|
}
|
|
if razaoSocial.Valid {
|
|
tenant.RazaoSocial = razaoSocial.String
|
|
}
|
|
if email.Valid {
|
|
tenant.Email = email.String
|
|
}
|
|
if phone.Valid {
|
|
tenant.Phone = phone.String
|
|
}
|
|
if website.Valid {
|
|
tenant.Website = website.String
|
|
}
|
|
if address.Valid {
|
|
tenant.Address = address.String
|
|
}
|
|
if city.Valid {
|
|
tenant.City = city.String
|
|
}
|
|
if state.Valid {
|
|
tenant.State = state.String
|
|
}
|
|
if zip.Valid {
|
|
tenant.Zip = zip.String
|
|
}
|
|
if description.Valid {
|
|
tenant.Description = description.String
|
|
}
|
|
if industry.Valid {
|
|
tenant.Industry = industry.String
|
|
}
|
|
|
|
return tenant, nil
|
|
}
|
|
|
|
// FindBySubdomain finds a tenant by subdomain
|
|
func (r *TenantRepository) FindBySubdomain(subdomain string) (*domain.Tenant, error) {
|
|
query := `
|
|
SELECT id, name, domain, subdomain, created_at, updated_at
|
|
FROM tenants
|
|
WHERE subdomain = $1
|
|
`
|
|
|
|
tenant := &domain.Tenant{}
|
|
err := r.db.QueryRow(query, subdomain).Scan(
|
|
&tenant.ID,
|
|
&tenant.Name,
|
|
&tenant.Domain,
|
|
&tenant.Subdomain,
|
|
&tenant.CreatedAt,
|
|
&tenant.UpdatedAt,
|
|
)
|
|
|
|
if err == sql.ErrNoRows {
|
|
return nil, nil
|
|
}
|
|
|
|
return tenant, err
|
|
}
|
|
|
|
// SubdomainExists checks if a subdomain is already taken
|
|
func (r *TenantRepository) SubdomainExists(subdomain string) (bool, error) {
|
|
var exists bool
|
|
query := `SELECT EXISTS(SELECT 1 FROM tenants WHERE subdomain = $1)`
|
|
err := r.db.QueryRow(query, subdomain).Scan(&exists)
|
|
return exists, err
|
|
}
|
|
|
|
// FindAll returns all tenants
|
|
func (r *TenantRepository) FindAll() ([]*domain.Tenant, error) {
|
|
query := `
|
|
SELECT id, name, domain, subdomain, is_active, created_at, updated_at
|
|
FROM tenants
|
|
ORDER BY created_at DESC
|
|
`
|
|
|
|
rows, err := r.db.Query(query)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
|
|
var tenants []*domain.Tenant
|
|
for rows.Next() {
|
|
tenant := &domain.Tenant{}
|
|
err := rows.Scan(
|
|
&tenant.ID,
|
|
&tenant.Name,
|
|
&tenant.Domain,
|
|
&tenant.Subdomain,
|
|
&tenant.IsActive,
|
|
&tenant.CreatedAt,
|
|
&tenant.UpdatedAt,
|
|
)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
tenants = append(tenants, tenant)
|
|
}
|
|
|
|
if tenants == nil {
|
|
return []*domain.Tenant{}, nil
|
|
}
|
|
|
|
return tenants, nil
|
|
}
|
|
|
|
// Delete removes a tenant (and cascades to related data)
|
|
func (r *TenantRepository) Delete(id uuid.UUID) error {
|
|
result, err := r.db.Exec(`DELETE FROM tenants WHERE id = $1`, id)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
rows, err := result.RowsAffected()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if rows == 0 {
|
|
return sql.ErrNoRows
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// UpdateProfile updates tenant profile information
|
|
func (r *TenantRepository) UpdateProfile(id uuid.UUID, updates map[string]interface{}) error {
|
|
query := `
|
|
UPDATE tenants SET
|
|
name = COALESCE($1, name),
|
|
cnpj = COALESCE($2, cnpj),
|
|
razao_social = COALESCE($3, razao_social),
|
|
email = COALESCE($4, email),
|
|
phone = COALESCE($5, phone),
|
|
website = COALESCE($6, website),
|
|
address = COALESCE($7, address),
|
|
city = COALESCE($8, city),
|
|
state = COALESCE($9, state),
|
|
zip = COALESCE($10, zip),
|
|
description = COALESCE($11, description),
|
|
industry = COALESCE($12, industry),
|
|
updated_at = $13
|
|
WHERE id = $14
|
|
`
|
|
|
|
_, err := r.db.Exec(
|
|
query,
|
|
updates["name"],
|
|
updates["cnpj"],
|
|
updates["razao_social"],
|
|
updates["email"],
|
|
updates["phone"],
|
|
updates["website"],
|
|
updates["address"],
|
|
updates["city"],
|
|
updates["state"],
|
|
updates["zip"],
|
|
updates["description"],
|
|
updates["industry"],
|
|
time.Now(),
|
|
id,
|
|
)
|
|
|
|
return err
|
|
}
|