photum/backend/internal/codigos/service.go
2026-02-03 11:29:45 -03:00

116 lines
2.5 KiB
Go

package codigos
import (
"context"
"time"
"photum-backend/internal/db/generated"
"github.com/google/uuid"
"github.com/jackc/pgx/v5/pgtype"
)
type Service struct {
q *generated.Queries
}
func NewService(q *generated.Queries) *Service {
return &Service{
q: q,
}
}
type CreateCodigoInput struct {
Codigo string `json:"codigo"`
Descricao string `json:"descricao"`
ValidadeDias int32 `json:"validade_dias"`
EmpresaID string `json:"empresa_id"`
}
func (s *Service) Create(ctx context.Context, input CreateCodigoInput) (generated.CodigosAcesso, error) {
days := input.ValidadeDias
var expiraEm time.Time
if days == -1 {
// Infinite: 100 years
expiraEm = time.Now().AddDate(100, 0, 0)
} else {
if days <= 0 {
days = 30
}
expiraEm = time.Now().Add(time.Duration(days) * 24 * time.Hour)
}
var empresaUUID pgtype.UUID
if input.EmpresaID != "" {
parsed, err := uuid.Parse(input.EmpresaID)
if err == nil {
empresaUUID.Bytes = parsed
empresaUUID.Valid = true
}
}
return s.q.CreateCodigoAcesso(ctx, generated.CreateCodigoAcessoParams{
Codigo: input.Codigo,
Descricao: pgtype.Text{String: input.Descricao, Valid: input.Descricao != ""},
ValidadeDias: days,
ExpiraEm: pgtype.Timestamptz{Time: expiraEm, Valid: true},
Ativo: true,
EmpresaID: empresaUUID,
})
}
func (s *Service) List(ctx context.Context) ([]generated.ListCodigosAcessoRow, error) {
return s.q.ListCodigosAcesso(ctx)
}
func (s *Service) Delete(ctx context.Context, id string) error {
uid, err := uuid.Parse(id)
if err != nil {
return err
}
// Convert uuid.UUID to pgtype.UUID
var pgUUID pgtype.UUID
pgUUID.Bytes = uid
pgUUID.Valid = true
return s.q.DeleteCodigoAcesso(ctx, pgUUID)
}
func (s *Service) GetByCode(ctx context.Context, code string) (generated.GetCodigoAcessoRow, error) {
return s.q.GetCodigoAcesso(ctx, code)
}
func (s *Service) IncrementUse(ctx context.Context, id uuid.UUID) error {
var pgUUID pgtype.UUID
pgUUID.Bytes = id
pgUUID.Valid = true
return s.q.IncrementCodigoAcessoUso(ctx, pgUUID)
}
// Custom error for validation
type AppError struct {
Message string
}
func (e *AppError) Error() string {
return e.Message
}
func (s *Service) Verify(ctx context.Context, code string) (*generated.GetCodigoAcessoRow, error) {
c, err := s.q.GetCodigoAcesso(ctx, code)
if err != nil {
return nil, err // Not found or DB error
}
if !c.Ativo {
return nil, &AppError{Message: "Código inativo"}
}
if time.Now().After(c.ExpiraEm.Time) {
return nil, &AppError{Message: "Código expirado"}
}
return &c, nil
}