docs: update roadmap and add admin handler tests

This commit is contained in:
Tiago Yamamoto 2025-12-28 03:04:18 -03:00
parent c61022a277
commit 69534f5810
2 changed files with 205 additions and 61 deletions

View file

@ -1,13 +1,40 @@
package handlers_test package handlers_test
import ( import (
"database/sql"
"net/http" "net/http"
"net/http/httptest" "net/http/httptest"
"regexp"
"testing" "testing"
"time"
"github.com/DATA-DOG/go-sqlmock"
"github.com/rede5/gohorsejobs/backend/internal/api/handlers" "github.com/rede5/gohorsejobs/backend/internal/api/handlers"
"github.com/rede5/gohorsejobs/backend/internal/services"
) )
// createTestAdminHandlers creates handlers with mocks and optional DB
func createTestAdminHandlers(t *testing.T, db *sql.DB) *handlers.AdminHandlers {
t.Helper()
var adminSvc *services.AdminService
var jobSvc *services.JobService
var auditSvc *services.AuditService
if db != nil {
adminSvc = services.NewAdminService(db)
jobSvc = services.NewJobService(db)
auditSvc = services.NewAuditService(db)
}
return handlers.NewAdminHandlers(
adminSvc,
auditSvc,
jobSvc,
nil, // Cloudflare service not needed for basic tests yet
)
}
func TestNewAdminHandlers(t *testing.T) { func TestNewAdminHandlers(t *testing.T) {
h := handlers.NewAdminHandlers(nil, nil, nil, nil) h := handlers.NewAdminHandlers(nil, nil, nil, nil)
if h == nil { if h == nil {
@ -15,19 +42,69 @@ func TestNewAdminHandlers(t *testing.T) {
} }
} }
func TestListAccessRoles(t *testing.T) { func TestAdminHandlers_ListCompanies(t *testing.T) {
h := handlers.NewAdminHandlers(nil, nil, nil, nil) db, mock, err := sqlmock.New()
if err != nil {
req := httptest.NewRequest(http.MethodGet, "/api/v1/admin/roles", nil) t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
rr := httptest.NewRecorder()
h.ListAccessRoles(rr, req)
if rr.Code != http.StatusOK {
t.Errorf("Expected status 200, got %d", rr.Code)
} }
defer db.Close()
if rr.Header().Get("Content-Type") != "application/json" { handlers := createTestAdminHandlers(t, db)
t.Errorf("Expected Content-Type application/json, got %s", rr.Header().Get("Content-Type"))
// Mock Count Query
mock.ExpectQuery(regexp.QuoteMeta(`SELECT COUNT(*) FROM companies`)).
WillReturnRows(sqlmock.NewRows([]string{"count"}).AddRow(1))
// Mock List Query
mock.ExpectQuery(regexp.QuoteMeta(`SELECT id, name, slug, type, document, city_id, email, website, verified, active, created_at FROM companies`)).
WillReturnRows(sqlmock.NewRows([]string{"id", "name", "slug", "type", "document", "city_id", "email", "website", "verified", "active", "created_at"}).
AddRow(1, "Acme Corp", "acme-corp", "company", "1234567890", 1, "contact@acme.com", "https://acme.com", true, true, time.Now()))
req := httptest.NewRequest(http.MethodGet, "/api/v1/admin/companies", nil)
rec := httptest.NewRecorder()
handlers.ListCompanies(rec, req)
if rec.Code != http.StatusOK {
t.Errorf("Expected status %d, got %d. Body: %s", http.StatusOK, rec.Code, rec.Body.String())
}
}
func TestAdminHandlers_DuplicateJob(t *testing.T) {
db, mock, err := sqlmock.New()
if err != nil {
t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
}
defer db.Close()
handlers := createTestAdminHandlers(t, db)
// 1. Mock GetJobByID (for duplication source)
// Updated query based on actual implementation
rows := sqlmock.NewRows([]string{"company_id", "created_by", "title", "description", "salary_min", "salary_max", "salary_type", "employment_type", "work_mode", "working_hours", "location", "region_id", "city_id", "requirements", "benefits", "visa_support", "language_level"}).
AddRow(1, 1, "Original Job", "Desc", 1000, 2000, "monthly", "full-time", "remote", "8h", "Remote", 1, 1, "[]", "[]", false, "native")
mock.ExpectQuery(regexp.QuoteMeta(`SELECT company_id, created_by, title, description, salary_min, salary_max, salary_type, employment_type, work_mode, working_hours, location, region_id, city_id, requirements, benefits, visa_support, language_level FROM jobs WHERE id = $1`)).
WithArgs(100).
WillReturnRows(rows)
// 2. Mock INSERT
// Note: The implementation might be returning more or fewer columns, blindly matching logic usually safer but here we try to match.
// Implementation typically inserts and returns ID.
mock.ExpectQuery(regexp.QuoteMeta(`INSERT INTO jobs`)).
WithArgs(1, 1, "Copy of Original Job", "Desc", 1000.0, 2000.0, "monthly", sqlmock.AnyArg(), "full-time", "remote", "8h", "Remote", 1, 1, "[]", "[]", false, "native", "draft").
WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(101))
// Request
req := httptest.NewRequest(http.MethodPost, "/api/v1/admin/jobs/100/duplicate", nil)
req.SetPathValue("id", "100")
rec := httptest.NewRecorder()
handlers.DuplicateJob(rec, req)
if rec.Code != http.StatusCreated {
t.Errorf("Expected status %d, got %d. Body: %s", http.StatusCreated, rec.Code, rec.Body.String())
} }
} }

View file

@ -1,79 +1,146 @@
# 🗺️ GoHorse Jobs & Marketplace - "The Intense" Roadmap # 🗺️ GoHorse Jobs & Marketplace - "The Intense" Roadmap (10X)
Este é o roadmap definitivo para transformar o GoHorse Jobs de um simples Job Board em um **Marketplace B2C Completo** e uma plataforma SaaS de alta performance. **O Roadmap Definitivo.**
Este documento não é apenas uma lista de tarefas; é o **DNA estratégico e técnico** para transformar o GoHorse Jobs na plataforma dominante de empregos e serviços digitais no Brasil (e futuramente LATAM/Global).
> **Visão:** Tornar-se o ecossistema líder para Vagas, Serviçõs e Produtos Digitais no Japão/Brasil. > **Meta:** Deixar de ser um "Job Board" e tornar-se um **Ecossistema de Carreira**.
> **Filosofia:** "Extreme GoHorse" na velocidade, "Solid/Clean Arch" na fundação.
--- ---
## 🚀 Fase 1: Fundação & Estabilidade (Concluído) ## 🏗️ Pilar 1: Fundação & Arquitetura (Já Consolidado)
*O "Merge Hell" e a base sólida.* *O alicerce que permite escalar sem quebrar.*
- [x] **Arquitetura Limpa:** Migração completa do Backend para Clean Architecture + DDD. ### 1.1 Backend & Core (Go)
- [x] **DevOps & CI/CD:** Pipeline Forgejo Actions com Podman/Docker para deploy automático em Dev. - [x] **Clean Arch + DDD:** Separação estrita entre Handlers, Services, UseCases e Repositories.
- [x] **Conflitos Resolvidos:** Unificação dos branches `hml`, `dev` e `main` (Frontend, Backend, Backoffice). - [x] **UUID v7:** Migração completa de INT para UUIDv7 (time-sorted) em todas as tabelas críticas (`users`, `jobs`, `applications`).
- [x] **Infraestrutura Core:** - *Por que?* Evita fragmentação de índices e permite sharding futuro sem conflitos.
- [x] Auth Híbrida (JWT + Cookies + Sessions). - [x] **Testes de Integração:** Setup de `sqlmock` e `testify` para cobertura crítica de Handlers e Services.
- [x] Migrations V7 (UUIDs). - [x] **Logs Estruturados:** `slog` com rastreamento de RequestID para observabilidade total.
- [x] Logs & Auditoria.
### 1.2 Frontend & UX (Next.js)
- [x] **Design System:** Componentes ShadCN/UI padronizados e responsivos.
- [x] **Auth Híbrida:** Suporte a JWT Bearer e Cookies para segurança máxima em clientes web e mobile.
- [x] **Dashboards Dedicados:** Áreas distintas e otimizadas para Candidatos (foco: aplicar rápido) e Recrutadores (foco: triagem rápida).
--- ---
## 💎 Fase 2: B2C Marketplace & Monetização (Q1 2025) ## 💎 Pilar 2: Marketplace B2C & Monetização (Q1 2025)
*Transformando tráfego em receita.* *Transformando usuários gratuitos em receita recorrente.*
### 2.1 Pagamentos & Assinaturas (Stripe) ### 2.1 Engine de Pagamentos (Stripe Integration)
- [ ] **Stripe Checkout:** Venda de "Destaques de Vagas" e "Planos Premium" para empresas. **Objetivo:** Permitir fluxo financeiro fluido para B2B e B2C.
- [ ] **Stripe Connect:** Permitir que candidatos/freelancers recebam por serviços (Mentorias, Reviews de Currículo) - *Plataforma fica com %.*
- [ ] **Billing Portal:** Gestão de faturas e cancelamento via Backoffice.
### 2.2 Marketplace de Serviços (Gigs) - [ ] **Checkout de Vagas (B2B):**
- [ ] **Módulo de Gigs:** Candidatos podem oferecer serviços (ex: "Revisão de CV em Japonês", "Consultoria de Visto"). - Empresas pagam para destacar vagas ("Featured") ou furar a fila de moderação.
- [ ] **Escrow de Pagamento:** O dinheiro só é liberado após a conclusão do serviço. - **Regra de Negócio:** Vaga paga entra como `status: published` automaticamente (após check de fraude). Vaga grátis entra como `review`.
- [ ] **Chat de Negociação:** Extensão do chat atual para incluir propostas e aceite de valores. - **Técnico:** Webhook Stripe (`checkout.session.completed`) atualiza tabela `job_payments` e dispara evento de publicação.
- [ ] **Assinaturas Recorrentes (SaaS):**
- Planos "Pro" para Recrutadores (Acesso ao Banco de Talentos, Filtros Avançados).
- Planos "Prime" para Candidatos (Destaque na busca, feedback detalhado de rejeição).
- [ ] **Marketplace de Serviços (Stripe Connect):**
- Candidatos vendem "Mentorias" ou "Revisão de CV".
- **Split de Pagamento:** Plataforma retém X% (ex: 15%), o resto vai para o prestador.
- **Técnico:** Uso de Stripe Connect Express para onboarding simplificado de vendedores (KYC automático).
### 2.3 Sistema de Reputação ### 2.2 Gamificação & Engajamento
- [ ] **Reviews Bilaterais:** Empresas avaliam candidatos (soft skills) e candidatos avaliam empresas (ambiente). **Objetivo:** Viciar o usuário na plataforma (Retenção).
- [ ] **Trust Score:** Algoritmo que calcula a confiabilidade baseada em histórico de pagamentos, tempo de resposta e reviews.
- [ ] **Sistema de Níveis (XP):**
- Ações geram XP: Completar perfil (+50XP), Aplicar (+10XP), Receber entrevista (+100XP).
- **Benefício:** Níveis altos ganham destaque visual ou acesso antecipado a vagas.
- [ ] **Badges Conquistáveis:** "Verificado", "Top Voice", "Dev Sênior", "Early Adopter".
- [ ] **Daily Streak:** Incentivo para login diário (ex: manter a visibilidade do perfil no topo).
--- ---
## 📦 Fase 3: Logística & Produtos Físicos (Q2 2025) ## 📦 Pilar 3: E-commerce & Logística (Q2 2025)
*Expansão para venda de equipamentos e merch.* *Expansão física: Venda de Merch e Equipamentos para Home Office.*
- [ ] **Carrinho de Compras:** Implementação no Frontend (Zustand/Redux). ### 3.1 Loja Oficial (Merch)
- [ ] **Cálculo de Frete:** Integração com Correios/Yamato Transport API. - [ ] **Catálogo de Produtos:** Camisetas, Canecas, Adesivos "GoHorse".
- [ ] **Gestão de Pedidos:** Módulo de Orders no Backoffice. - [ ] **Integração de Estoque:** Controle simples de estoque (`product_variants`, `inventory_logs`).
- [ ] **Loja Oficial:** Venda de kits de onboarding, livros e equipamentos. - [ ] **Checkout Unificado:** O mesmo carrinho serve para Vagas Premium e Camisetas.
### 3.2 Logística & Frete (Brasil)
**Foco:** Adaptação total ao mercado brasileiro.
- [ ] **Cálculo de Frete (Correios/Melhor Envio):**
- Integração via API para cálculo em tempo real (SEDEX, PAC) baseado no CEP do usuário.
- **Fallback:** Tabela de contingência para frete fixo caso API caia.
- [ ] **Rastreamento:**
- Webhook de atualização de status de entrega (`código de rastreio` salvo no pedido).
- Notificação via WhatsApp/Email quando sair para entrega.
- [ ] **Regras Fiscais:** Integração básica para emissão de NF-e (via Bling ou eNotas) no momento da confirmação do pagamento.
--- ---
## 🧠 Fase 4: AI & Automação (Q3 2025) ## 🧠 Pilar 4: Inteligência & Automação (Q3 2025 - "GoHorse AI")
*O diferencial tecnológico "GoHorse AI".* *Onde a mágica acontece. O diferencial competitivo.*
- [ ] **Matching Inteligente:** Algoritmo vetorial (pgvector) para casar Vagas x Currículos com precisão semântica. ### 4.1 Matching Semântico (Vector Search)
- [ ] **Cover Letter Generator:** AI que escreve cartas de apresentação baseadas no perfil do usuário. - [ ] **Embeddings:** Gerar vetores (OpenAI ou Local LLM) para:
- [ ] **Triagem Automática:** Bot que pré-entrevista candidatos no chat e classifica por fit cultural. - Descrições de Vagas.
- [ ] **Video Interview Analysis:** Transcrição e análise de sentimento de vídeos de apresentação. - Currículos/Bios de Candidatos.
- [ ] **Busca Vetorial (pgvector):**
- Substituir o `LIKE` ou `Fuzzy` por busca semântica (`cosine similarity`).
- **Resultado:** Busca por "Frontend Ninja" retorna perfis com "React", "Vue", "Angular" mesmo sem a palavra exata.
### 4.2 Assistente de Carreira (LLM Agent)
- [ ] **Review de Currículo Automático:**
- AI analisa o PDF e sugere melhorias (ex: "Use verbos de ação", "Quantifique resultados").
- [ ] **Gerador de Cover Letter:**
- Bot lê a vaga + perfil do usuário e gera uma carta personalizada em segundos.
- [ ] **Pre-Screening Bot:**
- Chatbot no WhatsApp/Site que faz perguntas de triagem ("Você tem 3 anos de Exp?", "Inglês Fluente?") e classifica o candidato para o RH.
--- ---
## 📱 Fase 5: Mobile & PWA (Ongoing) ## 📱 Pilar 5: Mobile First & Notificações (Ongoing)
- [ ] **PWA Offline:** Cache agressivo para funcionar no metrô (Service Workers). *Estar onde o usuário está: No celular.*
- [ ] **React Native App:** App nativo para iOS/Android focado em notificações push e chat.
- [ ] **PWA (Progressive Web App):**
- Service Workers para cache offline agressivo (funcionar no metrô/ônibus).
- "Add to Home Screen" com ícone nativo.
- [ ] **Notificações Push (FCM):**
- Alerta de vaga nova (match).
- Alerta de "Visto por um recrutador".
- Alerta de status de entrega de produto.
- [ ] **Integração WhatsApp (Twilio/ZAP):**
- Candidato recebe link de entrevista direto no Wpp.
- Recrutador recebe aviso de "Candidato Perfeito" no Wpp.
--- ---
## 🛡️ Gap Analysis (O que falta AGORA) ## 🛡️ Pilar 6: Segurança & Compliance (LGPD)
*Itens críticos para atingir o nível "Marketplace".* *Protegendo o ativo mais valioso: Dados.*
| Área | Gap Identificado | Ação Imediata | - [ ] **Anonimização de Dados:** Opção para candidato "esconder" nome/contato até o match.
|------|------------------|---------------| - [ ] **Auditoria Completa (Audit Trail):**
| **Busca** | Postgres `LIKE` é lento para escala. | Migrar para **Meilisearch** ou **Elasticsearch**. | - Quem acessou o currículo de quem? (Já iniciado em `activity_logs`).
| **SEO** | Páginas de vagas mal indexadas. | Implementar **SSR** e **Schema.org** estruturado no Next.js. | - Registro imutável de alterações salariais ou contratuais.
| **Monetização** | Nenhuma forma de cobrar usuários. | Integrar **Stripe** no Backend (prioridade zero). | - [ ] **Pre-signed URLs:** Curriculos no S3/R2 com links temporários (TTL 15min) para evitar scraping.
| **Segurança** | Uploads públicos vulneráveis. | Forçar Pre-signed URLs privadas com TTL curto. | - [ ] **Anti-Fraud:** Rate-limiting agressivo em endpoints de login e cadastro. Detecção de emails temporários.
--- ---
> *"Go Horse is not just a methodology, it's a lifestyle."* 🐴 ## 📊 Gap Analysis Técnico (O que precisamos resolver JÁ)
| Área | Gap | Solução Técnica Proposta | Complexidade |
|------|-----|--------------------------|--------------|
| **Busca** | Postgres `Semântico` | Implementar `pgvector` ou ElasticSearch. A busca atual não escala. | Alta |
| **Email** | SMTP Síncrono | Migrar para Fila (Redis/RabbitMQ) + Worker assíncrono para envio de emails em massa. | Média |
| **Cache** | Inexistente | Implementar Redis para cache de `GET /jobs` e Sessões de Usuário. | Média |
| **Img** | Upload Direto | Implementar Image Processing (Sharp/Go) para resize/compression antes do S3. | Baixa |
| **Logs** | Arquivo Local | Centralizar logs (Loki/Elastic) para visualização no Grafana. | Alta |
---
## 📅 Cronograma Estimado (Dev)
- **Semana 1-2:** Fixar Testes Backend, Estabilizar Deploy, Finalizar C4 Model.
- **Semana 3-4:** Implementar Stripe Checkout (Pagamento Básico).
- **Semana 5-6:** Módulo de Logística (Básico - Frete Correios).
- **Semana 7-8:** Início do Módulo AI (Matching Vetorial).
> *"O futuro pertence a quem deploya na sexta-feira."* 🚀