photum/backend/internal/cadastro_fot/service.go
NANDO9322 765496065a feat: suporte a FOT alfanumérico e correções de UI
Backend:
- Migration 007: alterada coluna `fot` de INTEGER para VARCHAR(50).
- Ajustados serviços (finance, agenda) e handlers para processar FOT como string.
- Regenerados modelos e queries do banco de dados (sqlc).

Frontend:
- [FotForm](cci:1://file:///c:/Projetos/photum/frontend/components/FotForm.tsx:13:0-348:2): Permitido input de texto/alfanumérico (ex: "20000MG").
- [EventTable](cci:1://file:///c:/Projetos/photum/frontend/components/EventTable.tsx:29:0-684:2): Removido bloqueio do botão "Aprovar" para equipes incompletas.
- [Dashboard](cci:1://file:///c:/Projetos/photum/frontend/pages/Dashboard.tsx:31:0-1749:2): Corrigida duplicação do campo "Qtd Formandos".
- [Dashboard](cci:1://file:///c:/Projetos/photum/frontend/pages/Dashboard.tsx:31:0-1749:2): Filtros de "Gerenciar Equipe" agora usam funções dinâmicas (IDs) em vez de valores fixos.
- `Navbar`: Logo agora redireciona corretamente para `/painel`.
2026-01-29 22:15:14 -03:00

121 lines
4.1 KiB
Go

package cadastro_fot
import (
"context"
"errors"
"strconv"
"photum-backend/internal/db/generated"
"github.com/google/uuid"
"github.com/jackc/pgx/v5/pgtype"
)
type Service struct {
queries *generated.Queries
}
func NewService(queries *generated.Queries) *Service {
return &Service{queries: queries}
}
type CreateInput struct {
Fot string `json:"fot"`
EmpresaID string `json:"empresa_id"`
CursoID string `json:"curso_id"`
AnoFormaturaID string `json:"ano_formatura_id"`
Instituicao string `json:"instituicao"`
Cidade string `json:"cidade"`
Estado string `json:"estado"`
Observacoes string `json:"observacoes"`
GastosCaptacao float64 `json:"gastos_captacao"`
PreVenda bool `json:"pre_venda"`
}
func (s *Service) Create(ctx context.Context, input CreateInput) (*generated.CadastroFot, error) {
empresaUUID, _ := uuid.Parse(input.EmpresaID)
cursoUUID, _ := uuid.Parse(input.CursoID)
anoUUID, _ := uuid.Parse(input.AnoFormaturaID)
res, err := s.queries.CreateCadastroFot(ctx, generated.CreateCadastroFotParams{
Fot: input.Fot,
EmpresaID: pgtype.UUID{Bytes: empresaUUID, Valid: true},
CursoID: pgtype.UUID{Bytes: cursoUUID, Valid: true},
AnoFormaturaID: pgtype.UUID{Bytes: anoUUID, Valid: true},
Instituicao: pgtype.Text{String: input.Instituicao, Valid: true},
Cidade: pgtype.Text{String: input.Cidade, Valid: true},
Estado: pgtype.Text{String: input.Estado, Valid: true},
Observacoes: pgtype.Text{String: input.Observacoes, Valid: true},
GastosCaptacao: toPgNumeric(input.GastosCaptacao),
PreVenda: pgtype.Bool{Bool: input.PreVenda, Valid: true},
})
if err != nil {
return nil, err
}
return &res, nil
}
func (s *Service) List(ctx context.Context) ([]generated.ListCadastroFotRow, error) {
return s.queries.ListCadastroFot(ctx)
}
func (s *Service) ListByEmpresa(ctx context.Context, empresaID string) ([]generated.ListCadastroFotByEmpresaRow, error) {
uuidVal, err := uuid.Parse(empresaID)
if err != nil {
return nil, errors.New("invalid empresa_id")
}
// Note: ListCadastroFotByEmpresaRow is nearly identical to ListCadastroFotRow but we use the generated type
return s.queries.ListCadastroFotByEmpresa(ctx, pgtype.UUID{Bytes: uuidVal, Valid: true})
}
func (s *Service) GetByID(ctx context.Context, id string) (*generated.GetCadastroFotByIDRow, error) {
uuidVal, err := uuid.Parse(id)
if err != nil {
return nil, errors.New("invalid id")
}
item, err := s.queries.GetCadastroFotByID(ctx, pgtype.UUID{Bytes: uuidVal, Valid: true})
return &item, err
}
func (s *Service) Update(ctx context.Context, id string, input CreateInput) (*generated.CadastroFot, error) {
uuidVal, err := uuid.Parse(id)
if err != nil {
return nil, errors.New("invalid id")
}
empresaUUID, _ := uuid.Parse(input.EmpresaID)
cursoUUID, _ := uuid.Parse(input.CursoID)
anoUUID, _ := uuid.Parse(input.AnoFormaturaID)
item, err := s.queries.UpdateCadastroFot(ctx, generated.UpdateCadastroFotParams{
ID: pgtype.UUID{Bytes: uuidVal, Valid: true},
Fot: input.Fot,
EmpresaID: pgtype.UUID{Bytes: empresaUUID, Valid: true},
CursoID: pgtype.UUID{Bytes: cursoUUID, Valid: true},
AnoFormaturaID: pgtype.UUID{Bytes: anoUUID, Valid: true},
Instituicao: pgtype.Text{String: input.Instituicao, Valid: true},
Cidade: pgtype.Text{String: input.Cidade, Valid: true},
Estado: pgtype.Text{String: input.Estado, Valid: true},
Observacoes: pgtype.Text{String: input.Observacoes, Valid: true},
GastosCaptacao: toPgNumeric(input.GastosCaptacao),
PreVenda: pgtype.Bool{Bool: input.PreVenda, Valid: true},
})
return &item, err
}
func (s *Service) Delete(ctx context.Context, id string) error {
uuidVal, err := uuid.Parse(id)
if err != nil {
return errors.New("invalid id")
}
return s.queries.DeleteCadastroFot(ctx, pgtype.UUID{Bytes: uuidVal, Valid: true})
}
// Helper to convert float to numeric robustly
func toPgNumeric(f float64) pgtype.Numeric {
var n pgtype.Numeric
s := strconv.FormatFloat(f, 'f', -1, 64)
if err := n.Scan(s); err != nil {
return pgtype.Numeric{Valid: false}
}
return n
}