gohorsejobs/backend/internal/services/application_service.go
NANDO9322 ddc2f5dd03 feat: atualiza fluxo de cadastro de candidatos com persistência completa de dados e máscara de telefone
Frontend:
- Implementar máscara de entrada de telefone para números BR ((XX) XXXXX-XXXX).
- Atualizar formulário de cadastro para enviar dados completos do perfil do candidato (endereço, formação, habilidades, etc.).
- Corrigir problemas de idioma misto na página de Detalhes da Vaga e adicionar traduções faltantes.

Backend:
- Atualizar modelo de Usuário, Entidade e DTOs para incluir campos de perfil (Data de Nascimento, Endereço, Formação, etc.).
- Atualizar UserRepository para persistir e recuperar os dados estendidos do usuário no PostgreSQL.
- Atualizar RegisterCandidateUseCase para mapear campos de entrada para a entidade Usuário.
2026-01-06 18:19:47 -03:00

187 lines
5.1 KiB
Go

package services
import (
"database/sql"
"time"
"github.com/rede5/gohorsejobs/backend/internal/dto"
"github.com/rede5/gohorsejobs/backend/internal/models"
)
type ApplicationService struct {
DB *sql.DB
}
func NewApplicationService(db *sql.DB) *ApplicationService {
return &ApplicationService{DB: db}
}
func (s *ApplicationService) CreateApplication(req dto.CreateApplicationRequest) (*models.Application, error) {
query := `
INSERT INTO applications (
job_id, user_id, name, phone, line_id, whatsapp, email,
message, resume_url, documents, status, created_at, updated_at
) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13)
RETURNING id, created_at, updated_at
`
app := &models.Application{
JobID: req.JobID,
UserID: req.UserID,
Name: req.Name,
Phone: req.Phone,
LineID: req.LineID,
WhatsApp: req.WhatsApp,
Email: req.Email,
Message: req.Message,
ResumeURL: req.ResumeURL,
Documents: req.Documents,
Status: "pending",
CreatedAt: time.Now(),
UpdatedAt: time.Now(),
}
err := s.DB.QueryRow(
query,
app.JobID, app.UserID, app.Name, app.Phone, app.LineID, app.WhatsApp, app.Email,
app.Message, app.ResumeURL, app.Documents, app.Status, app.CreatedAt, app.UpdatedAt,
).Scan(&app.ID, &app.CreatedAt, &app.UpdatedAt)
if err != nil {
return nil, err
}
return app, nil
}
func (s *ApplicationService) GetApplications(jobID string) ([]models.Application, error) {
// Simple get by Job ID
query := `
SELECT id, job_id, user_id, name, phone, line_id, whatsapp, email,
message, resume_url, status, created_at, updated_at
FROM applications WHERE job_id = $1
`
rows, err := s.DB.Query(query, jobID)
if err != nil {
return nil, err
}
defer rows.Close()
var apps []models.Application
for rows.Next() {
var a models.Application
if err := rows.Scan(
&a.ID, &a.JobID, &a.UserID, &a.Name, &a.Phone, &a.LineID, &a.WhatsApp, &a.Email,
&a.Message, &a.ResumeURL, &a.Status, &a.CreatedAt, &a.UpdatedAt,
); err != nil {
return nil, err
}
apps = append(apps, a)
}
return apps, nil
}
func (s *ApplicationService) GetApplicationByID(id string) (*models.Application, error) {
var a models.Application
query := `
SELECT id, job_id, user_id, name, phone, line_id, whatsapp, email,
message, resume_url, documents, status, created_at, updated_at
FROM applications WHERE id = $1
`
err := s.DB.QueryRow(query, id).Scan(
&a.ID, &a.JobID, &a.UserID, &a.Name, &a.Phone, &a.LineID, &a.WhatsApp, &a.Email,
&a.Message, &a.ResumeURL, &a.Documents, &a.Status, &a.CreatedAt, &a.UpdatedAt,
)
if err != nil {
return nil, err
}
return &a, nil
}
func (s *ApplicationService) UpdateApplicationStatus(id string, req dto.UpdateApplicationStatusRequest) (*models.Application, error) {
query := `
UPDATE applications SET status = $1, updated_at = NOW()
WHERE id = $2
RETURNING updated_at
`
var updatedAt time.Time
err := s.DB.QueryRow(query, req.Status, id).Scan(&updatedAt)
if err != nil {
return nil, err
}
return s.GetApplicationByID(id)
}
func (s *ApplicationService) GetApplicationsByCompany(companyID string) ([]models.Application, error) {
query := `
SELECT a.id, a.job_id, a.user_id, a.name, a.phone, a.line_id, a.whatsapp, a.email,
a.message, a.resume_url, a.status, a.created_at, a.updated_at
FROM applications a
JOIN jobs j ON a.job_id = j.id
WHERE j.company_id = $1
ORDER BY a.created_at DESC
`
rows, err := s.DB.Query(query, companyID)
if err != nil {
return nil, err
}
defer rows.Close()
var apps []models.Application
for rows.Next() {
var a models.Application
if err := rows.Scan(
&a.ID, &a.JobID, &a.UserID, &a.Name, &a.Phone, &a.LineID, &a.WhatsApp, &a.Email,
&a.Message, &a.ResumeURL, &a.Status, &a.CreatedAt, &a.UpdatedAt,
); err != nil {
return nil, err
}
apps = append(apps, a)
}
return apps, nil
}
func (s *ApplicationService) GetApplicationsByUser(userID string) ([]models.ApplicationWithDetails, error) {
query := `
SELECT
a.id, a.job_id, a.user_id, a.name, a.phone, a.line_id, a.whatsapp, a.email,
a.message, a.resume_url, a.status, a.created_at, a.updated_at,
j.title, c.name, j.company_id
FROM applications a
JOIN jobs j ON a.job_id = j.id
LEFT JOIN companies c ON j.company_id::text = c.id::text
WHERE a.user_id = $1
ORDER BY a.created_at DESC
`
rows, err := s.DB.Query(query, userID)
if err != nil {
return nil, err
}
defer rows.Close()
var apps []models.ApplicationWithDetails = []models.ApplicationWithDetails{}
for rows.Next() {
var a models.ApplicationWithDetails
var companyID sql.NullString
if err := rows.Scan(
&a.ID, &a.JobID, &a.UserID, &a.Name, &a.Phone, &a.LineID, &a.WhatsApp, &a.Email,
&a.Message, &a.ResumeURL, &a.Status, &a.CreatedAt, &a.UpdatedAt,
&a.JobTitle, &a.CompanyName, &companyID,
); err != nil {
return nil, err
}
if companyID.Valid {
a.CompanyID = companyID.String
}
apps = append(apps, a)
}
return apps, nil
}
func (s *ApplicationService) DeleteApplication(id string) error {
query := `DELETE FROM applications WHERE id = $1`
_, err := s.DB.Exec(query, id)
return err
}