csv de respuestas corregido

This commit is contained in:
Your Name
2025-04-25 09:37:58 -06:00
parent 14d191790f
commit 4e472e9e33
@@ -400,72 +400,114 @@ recibas tu constancia.</p>
throw new NotFoundException(`Cuestionario con ID ${idCuestionario} no encontrado`); throw new NotFoundException(`Cuestionario con ID ${idCuestionario} no encontrado`);
} }
// Obtener todas las respuestas para este cuestionario con sus relaciones // Obtener todas las preguntas del cuestionario para los encabezados
const respuestas = await this.dataSource.query(` const preguntas = await this.dataSource.query(`
SELECT SELECT
p.id_pregunta,
p.pregunta,
p.id_tipo_pregunta
FROM pregunta p
JOIN seccion_pregunta sp ON p.id_pregunta = sp.id_pregunta
JOIN seccion s ON sp.id_seccion = s.id_seccion
JOIN cuestionario_seccion cs ON s.id_seccion = cs.id_seccion
WHERE cs.id_cuestionario = ?
ORDER BY sp.posicion, p.id_pregunta
`, [idCuestionario]);
// Obtener los participantes que han respondido este cuestionario
const participantes = await this.dataSource.query(`
SELECT DISTINCT
cr.id_cuestionario_respondido, cr.id_cuestionario_respondido,
cr.fecha_respuesta, cr.fecha_respuesta,
p.id_participante, p.id_participante,
p.correo AS correo_participante, p.correo AS correo_participante
c.id_cuestionario,
c.nombre_form AS nombre_cuestionario,
e.id_evento,
e.nombre_evento,
preg.id_pregunta,
preg.pregunta,
-- Para respuestas abiertas
rpa.respuesta AS respuesta_abierta,
-- Para respuestas cerradas
o.id_opcion,
o.opcion AS respuesta_cerrada
FROM cuestionario_respondido cr FROM cuestionario_respondido cr
JOIN participante p ON cr.id_participante = p.id_participante JOIN participante p ON cr.id_participante = p.id_participante
JOIN cuestionario c ON cr.id_cuestionario = c.id_cuestionario WHERE cr.id_cuestionario = ?
LEFT JOIN evento e ON c.id_evento = e.id_evento ORDER BY cr.fecha_respuesta DESC
-- Respuestas abiertas
LEFT JOIN respuesta_participante_abierta rpa ON rpa.id_cuestionario_respondido = cr.id_cuestionario_respondido
LEFT JOIN pregunta preg_abierta ON rpa.id_pregunta = preg_abierta.id_pregunta
-- Respuestas cerradas
LEFT JOIN respuesta_participante_cerrada rpc ON rpc.id_cuestionario_respondido = cr.id_cuestionario_respondido
LEFT JOIN pregunta_opcion po ON rpc.id_pregunta_opcion = po.id_pregunta_opcion
LEFT JOIN pregunta preg ON po.id_pregunta = preg.id_pregunta
LEFT JOIN opcion o ON po.id_opcion = o.id_opcion
WHERE c.id_cuestionario = ?
ORDER BY cr.id_cuestionario_respondido, preg.id_pregunta
`, [idCuestionario]); `, [idCuestionario]);
// Obtener todas las respuestas para este cuestionario
const respuestasAbiertas = await this.dataSource.query(`
SELECT
cr.id_cuestionario_respondido,
p.id_pregunta,
rpa.respuesta
FROM respuesta_participante_abierta rpa
JOIN pregunta p ON rpa.id_pregunta = p.id_pregunta
JOIN cuestionario_respondido cr ON rpa.id_cuestionario_respondido = cr.id_cuestionario_respondido
WHERE cr.id_cuestionario = ?
`, [idCuestionario]);
const respuestasCerradas = await this.dataSource.query(`
SELECT
cr.id_cuestionario_respondido,
p.id_pregunta,
o.opcion
FROM respuesta_participante_cerrada rpc
JOIN pregunta_opcion po ON rpc.id_pregunta_opcion = po.id_pregunta_opcion
JOIN pregunta p ON po.id_pregunta = p.id_pregunta
JOIN opcion o ON po.id_opcion = o.id_opcion
JOIN cuestionario_respondido cr ON rpc.id_cuestionario_respondido = cr.id_cuestionario_respondido
WHERE cr.id_cuestionario = ?
`, [idCuestionario]);
// Crear un mapa de respuestas por participante y pregunta
const respuestasPorParticipante = new Map();
// Agregar respuestas abiertas al mapa
respuestasAbiertas.forEach(respuesta => {
const key = `${respuesta.id_cuestionario_respondido}_${respuesta.id_pregunta}`;
respuestasPorParticipante.set(key, respuesta.respuesta);
});
// Agregar respuestas cerradas al mapa (posiblemente múltiples por pregunta)
respuestasCerradas.forEach(respuesta => {
const key = `${respuesta.id_cuestionario_respondido}_${respuesta.id_pregunta}`;
const respuestaActual = respuestasPorParticipante.get(key);
if (respuestaActual) {
// Si ya hay una respuesta para esta pregunta, agregar esta opción
respuestasPorParticipante.set(key, `${respuestaActual}, ${respuesta.opcion}`);
} else {
respuestasPorParticipante.set(key, respuesta.opcion);
}
});
// Preparar los datos para el CSV // Preparar los datos para el CSV
const datosReporte: string[][] = []; const datosReporte: string[][] = [];
// Agregar encabezados // Agregar encabezados con datos del participante seguidos por las preguntas
const encabezados: string[] = [ const encabezados = [
'ID Respuesta',
'Fecha Respuesta',
'ID Participante', 'ID Participante',
'Correo Participante', 'Correo',
'Evento', 'Fecha Respuesta'
'Cuestionario',
'Pregunta',
'Respuesta'
]; ];
// Agregar cada pregunta como un encabezado
preguntas.forEach(pregunta => {
encabezados.push(pregunta.pregunta);
});
datosReporte.push(encabezados); datosReporte.push(encabezados);
// Procesar los resultados para el CSV // Crear una fila por cada participante
for (const fila of respuestas) { participantes.forEach(participante => {
const respuesta = fila.respuesta_abierta || fila.respuesta_cerrada || ''; const fila = [
participante.id_participante.toString(),
participante.correo_participante,
new Date(participante.fecha_respuesta).toLocaleString()
];
datosReporte.push([ // Agregar cada respuesta en el orden de las preguntas
fila.id_cuestionario_respondido?.toString() || '', preguntas.forEach(pregunta => {
new Date(fila.fecha_respuesta).toLocaleString(), const key = `${participante.id_cuestionario_respondido}_${pregunta.id_pregunta}`;
fila.id_participante?.toString() || '', const respuesta = respuestasPorParticipante.get(key) || '';
fila.correo_participante || '', fila.push(respuesta);
fila.nombre_evento || 'Sin evento', });
fila.nombre_cuestionario || '',
fila.pregunta || '', datosReporte.push(fila);
respuesta });
]);
}
// Generar CSV de forma manual con valores separados por comas y líneas con saltos de línea // Generar CSV de forma manual con valores separados por comas y líneas con saltos de línea
// Escapar valores que contengan comas para evitar problemas con el formato CSV // Escapar valores que contengan comas para evitar problemas con el formato CSV