photum/backend/internal/db/queries/agenda.sql
NANDO9322 20b60fcc27 feat(agenda): implementar sistema de conflito por tempo e horário de término
- db: criada migration para adicionar coluna `horario_fim` na tabela agenda
- backend: queries SQLC atualizadas para ler e gravar horario_fim
- backend: mapeamento no service.go modificado para incluir e retornar o horário
- backend: atualizada documentação das rotas (Swagger)
- frontend/ui: adicionado campo de input Horário de Término no EventForm
- frontend/ui: painéis do Dashboard e DailyLogistics renderizando o novo formato visual de exibição de horas do evento
- frontend/logic: atualizada validação de profissionais ocupados (busyProfessionalIds) para analisar colisão real com base no intervalo Início x Fim em vez do fechamento total do dia
- frontend/context: conserto no state global do DataContext para não perder a string do backend após edições via modal
2026-02-25 11:38:37 -03:00

264 lines
7.2 KiB
SQL

-- name: CreateAgenda :one
INSERT INTO agenda (
fot_id,
data_evento,
tipo_evento_id,
observacoes_evento,
local_evento,
endereco,
horario,
horario_fim,
qtd_formandos,
qtd_fotografos,
qtd_recepcionistas,
qtd_cinegrafistas,
qtd_estudios,
qtd_ponto_foto,
qtd_ponto_id,
qtd_ponto_decorado,
qtd_pontos_led,
qtd_plataforma_360,
status_profissionais,
foto_faltante,
recep_faltante,
cine_faltante,
logistica_observacoes,
pre_venda,
user_id,
regiao,
contatos
) VALUES (
$1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22, $23, $24, $25, @regiao, $26
) RETURNING *;
-- name: GetAgenda :one
SELECT * FROM agenda
WHERE id = $1 AND regiao = @regiao LIMIT 1;
-- name: ListAgendas :many
SELECT
a.*,
cf.fot as fot_numero,
cf.instituicao,
c.nome as curso_nome,
e.nome as empresa_nome,
af.ano_semestre,
cf.observacoes as observacoes_fot,
te.nome as tipo_evento_nome,
cf.empresa_id,
cf.finalizada as fot_finalizada,
cf.pre_venda as fot_pre_venda,
COALESCE(
(SELECT json_agg(json_build_object(
'professional_id', ap.profissional_id,
'status', ap.status,
'motivo_rejeicao', ap.motivo_rejeicao,
'funcao_id', ap.funcao_id,
'is_coordinator', ap.is_coordinator
))
FROM agenda_profissionais ap
WHERE ap.agenda_id = a.id),
'[]'::json
) as assigned_professionals
FROM agenda a
JOIN cadastro_fot cf ON a.fot_id = cf.id
JOIN cursos c ON cf.curso_id = c.id
JOIN empresas e ON cf.empresa_id = e.id
JOIN anos_formaturas af ON cf.ano_formatura_id = af.id
JOIN tipos_eventos te ON a.tipo_evento_id = te.id
WHERE a.regiao = @regiao
ORDER BY a.data_evento;
-- name: ListAgendasByUser :many
SELECT
a.*,
cf.fot as fot_numero,
cf.instituicao,
c.nome as curso_nome,
e.nome as empresa_nome,
af.ano_semestre,
cf.observacoes as observacoes_fot,
te.nome as tipo_evento_nome,
cf.empresa_id,
cf.finalizada as fot_finalizada,
cf.pre_venda as fot_pre_venda,
COALESCE(
(SELECT json_agg(json_build_object(
'professional_id', ap.profissional_id,
'status', ap.status,
'motivo_rejeicao', ap.motivo_rejeicao,
'funcao_id', ap.funcao_id,
'is_coordinator', ap.is_coordinator
))
FROM agenda_profissionais ap
WHERE ap.agenda_id = a.id),
'[]'::json
) as assigned_professionals
FROM agenda a
JOIN cadastro_fot cf ON a.fot_id = cf.id
JOIN cursos c ON cf.curso_id = c.id
JOIN empresas e ON cf.empresa_id = e.id
JOIN anos_formaturas af ON cf.ano_formatura_id = af.id
JOIN tipos_eventos te ON a.tipo_evento_id = te.id
WHERE a.user_id = $1 AND a.regiao = @regiao
ORDER BY a.data_evento;
-- name: UpdateAgenda :one
UPDATE agenda
SET
fot_id = $2,
data_evento = $3,
tipo_evento_id = $4,
observacoes_evento = $5,
local_evento = $6,
endereco = $7,
horario = $8,
horario_fim = $9,
qtd_formandos = $10,
qtd_fotografos = $11,
qtd_recepcionistas = $12,
qtd_cinegrafistas = $13,
qtd_estudios = $14,
qtd_ponto_foto = $15,
qtd_ponto_id = $16,
qtd_ponto_decorado = $17,
qtd_pontos_led = $18,
qtd_plataforma_360 = $19,
status_profissionais = $20,
foto_faltante = $21,
recep_faltante = $22,
cine_faltante = $23,
logistica_observacoes = $24,
pre_venda = $25,
contatos = $26,
atualizado_em = NOW()
WHERE id = $1 AND regiao = @regiao
RETURNING *;
-- name: DeleteAgenda :exec
DELETE FROM agenda
WHERE id = $1 AND regiao = @regiao;
-- name: AssignProfessional :exec
INSERT INTO agenda_profissionais (agenda_id, profissional_id, funcao_id)
VALUES ($1, $2, $3)
ON CONFLICT (agenda_id, profissional_id) DO UPDATE
SET funcao_id = EXCLUDED.funcao_id;
-- name: RemoveProfessional :exec
DELETE FROM agenda_profissionais
WHERE agenda_id = $1 AND profissional_id = $2;
-- name: GetAgendaProfessionals :many
SELECT p.*, f.nome as funcao_nome, u.email
FROM cadastro_profissionais p
JOIN agenda_profissionais ap ON p.id = ap.profissional_id
LEFT JOIN funcoes_profissionais f ON p.funcao_profissional_id = f.id
LEFT JOIN usuarios u ON p.usuario_id = u.id
WHERE ap.agenda_id = $1;
-- name: UpdateAgendaStatus :one
UPDATE agenda
SET status = $2, atualizado_em = NOW()
WHERE id = $1 AND regiao = @regiao
RETURNING *;
-- name: UpdateAssignmentStatus :one
UPDATE agenda_profissionais
SET status = $3, motivo_rejeicao = $4
WHERE agenda_id = $1 AND profissional_id = $2
RETURNING *;
-- name: UpdateAssignmentPosition :one
UPDATE agenda_profissionais
SET posicao = $3
WHERE agenda_id = $1 AND profissional_id = $2
RETURNING *;
-- name: ListAvailableProfessionalsForDate :many
SELECT
p.*,
u.email,
f.nome as funcao_nome,
dp.status as status_disponibilidade
FROM cadastro_profissionais p
JOIN usuarios u ON p.usuario_id = u.id
JOIN funcoes_profissionais f ON p.funcao_profissional_id = f.id
JOIN disponibilidade_profissionais dp ON u.id = dp.usuario_id
WHERE dp.data = $1
AND dp.status = 'DISPONIVEL'
AND p.regiao = @regiao
AND p.id NOT IN (
SELECT ap.profissional_id
FROM agenda_profissionais ap
JOIN agenda a ON ap.agenda_id = a.id
WHERE a.data_evento = $1
AND ap.status = 'ACEITO'
)
ORDER BY p.nome;
-- name: CheckProfessionalBusyDate :many
SELECT a.id, a.horario, a.horario_fim, ap.status
FROM agenda_profissionais ap
JOIN agenda a ON ap.agenda_id = a.id
WHERE ap.profissional_id = $1
AND a.data_evento = $2
AND ap.status = 'ACEITO'
AND a.id != $3;
-- name: ListAgendasByFot :many
SELECT
a.*,
te.nome as tipo_evento_nome
FROM agenda a
JOIN tipos_eventos te ON a.tipo_evento_id = te.id
WHERE a.fot_id = $1 AND a.regiao = @regiao
ORDER BY a.data_evento;
-- name: GetAgendaByFotDataTipo :one
SELECT * FROM agenda
WHERE fot_id = $1 AND data_evento = $2 AND tipo_evento_id = $3 AND regiao = @regiao
LIMIT 1;
-- name: ListAgendasByCompany :many
SELECT
a.*,
cf.fot as fot_numero,
cf.instituicao,
c.nome as curso_nome,
e.nome as empresa_nome,
af.ano_semestre,
cf.observacoes as observacoes_fot,
te.nome as tipo_evento_nome,
cf.empresa_id,
cf.finalizada as fot_finalizada,
cf.pre_venda as fot_pre_venda,
COALESCE(
(SELECT json_agg(json_build_object(
'professional_id', ap.profissional_id,
'status', ap.status,
'motivo_rejeicao', ap.motivo_rejeicao,
'funcao_id', ap.funcao_id,
'is_coordinator', ap.is_coordinator
))
FROM agenda_profissionais ap
WHERE ap.agenda_id = a.id),
'[]'::json
) as assigned_professionals
FROM agenda a
JOIN cadastro_fot cf ON a.fot_id = cf.id
JOIN cursos c ON cf.curso_id = c.id
JOIN empresas e ON cf.empresa_id = e.id
JOIN anos_formaturas af ON cf.ano_formatura_id = af.id
JOIN tipos_eventos te ON a.tipo_evento_id = te.id
WHERE cf.empresa_id = $1 AND a.regiao = @regiao
ORDER BY a.data_evento;
-- name: SetCoordinator :exec
UPDATE agenda_profissionais
SET is_coordinator = $3
WHERE agenda_id = $1 AND profissional_id = $2;
-- name: GetAssignment :one
SELECT * FROM agenda_profissionais
WHERE agenda_id = $1 AND profissional_id = $2;