Merge pull request 'registrar el evento cuando se crea en el formulario' (#10) from eithan into develop
Reviewed-on: #10
This commit was merged in pull request #10.
This commit is contained in:
@@ -11,6 +11,8 @@ import { Opcion } from '../opcion/entities/opcion.entity';
|
||||
import { PreguntaOpcion } from '../pregunta_opcion/entities/pregunta_opcion.entity';
|
||||
import { TipoPregunta } from '../tipo_pregunta/entities/tipo_pregunta.entity';
|
||||
import { TipoCuestionario } from '../tipo_cuestionario/entities/tipo_cuestionario.entity';
|
||||
import { Evento } from '../evento/evento.entity';
|
||||
import { EventoService } from '../evento/evento.service';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
@@ -23,11 +25,12 @@ import { TipoCuestionario } from '../tipo_cuestionario/entities/tipo_cuestionari
|
||||
Opcion,
|
||||
PreguntaOpcion,
|
||||
TipoPregunta,
|
||||
TipoCuestionario
|
||||
TipoCuestionario,
|
||||
Evento
|
||||
])
|
||||
],
|
||||
controllers: [CuestionarioController],
|
||||
providers: [CuestionarioService],
|
||||
providers: [CuestionarioService, EventoService],
|
||||
exports: [TypeOrmModule, CuestionarioService]
|
||||
})
|
||||
export class CuestionarioModule {}
|
||||
|
||||
@@ -12,6 +12,8 @@ import { Opcion } from '../opcion/entities/opcion.entity';
|
||||
import { PreguntaOpcion } from '../pregunta_opcion/entities/pregunta_opcion.entity';
|
||||
import { TipoPregunta } from '../tipo_pregunta/entities/tipo_pregunta.entity';
|
||||
import { TipoCuestionario } from '../tipo_cuestionario/entities/tipo_cuestionario.entity';
|
||||
import { Evento } from '../evento/evento.entity';
|
||||
import { EventoService } from '../evento/evento.service';
|
||||
|
||||
@Injectable()
|
||||
export class CuestionarioService {
|
||||
@@ -32,7 +34,10 @@ export class CuestionarioService {
|
||||
private preguntaOpcionRepository: Repository<PreguntaOpcion>,
|
||||
@InjectRepository(TipoPregunta)
|
||||
private tipoPreguntaRepository: Repository<TipoPregunta>,
|
||||
@InjectRepository(Evento)
|
||||
private eventoRepository: Repository<Evento>,
|
||||
private dataSource: DataSource,
|
||||
private eventoService: EventoService
|
||||
) {}
|
||||
|
||||
async create(createCuestionarioDto: CreateCuestionarioDto) {
|
||||
@@ -41,6 +46,33 @@ export class CuestionarioService {
|
||||
await queryRunner.startTransaction();
|
||||
|
||||
try {
|
||||
// Verificar si se especificó un evento y búscarlo/crearlo
|
||||
let idEvento: number | undefined = undefined;
|
||||
|
||||
if (createCuestionarioDto.evento) {
|
||||
// Buscar si el evento ya existe
|
||||
let evento = await this.eventoRepository.findOne({
|
||||
where: { nombre_evento: createCuestionarioDto.evento }
|
||||
});
|
||||
|
||||
// Si no existe, crearlo
|
||||
if (!evento) {
|
||||
const nuevoEvento = {
|
||||
nombre_evento: createCuestionarioDto.evento,
|
||||
tipo_evento: 'Predeterminado',
|
||||
fecha_inicio: createCuestionarioDto.fecha_inicio || new Date(),
|
||||
fecha_fin: createCuestionarioDto.fecha_fin || new Date(Date.now() + 86400000) // 1 día después si no hay fecha
|
||||
};
|
||||
|
||||
evento = await queryRunner.manager.save(Evento, nuevoEvento);
|
||||
console.log(`Evento creado: ${evento.nombre_evento}, ID: ${evento.id_evento}`);
|
||||
} else {
|
||||
console.log(`Evento encontrado: ${evento.nombre_evento}, ID: ${evento.id_evento}`);
|
||||
}
|
||||
|
||||
idEvento = evento.id_evento;
|
||||
}
|
||||
|
||||
// 1. Crear cuestionario
|
||||
const cuestionario = new Cuestionario();
|
||||
cuestionario.nombre_form = createCuestionarioDto.nombre_form;
|
||||
@@ -50,6 +82,11 @@ export class CuestionarioService {
|
||||
cuestionario.id_tipo_cuestionario = createCuestionarioDto.id_tipo_cuestionario;
|
||||
cuestionario.contador_secciones = createCuestionarioDto.secciones?.length || 0;
|
||||
cuestionario.editable = true;
|
||||
|
||||
// Asociar el cuestionario con el evento si existe
|
||||
if (idEvento !== undefined) {
|
||||
cuestionario.id_evento = idEvento;
|
||||
}
|
||||
|
||||
const savedCuestionario = await queryRunner.manager.save(cuestionario);
|
||||
|
||||
@@ -172,7 +209,8 @@ export class CuestionarioService {
|
||||
async findCompleto(id: number) {
|
||||
// Obtener el cuestionario básico
|
||||
const cuestionario = await this.cuestionarioRepository.findOne({
|
||||
where: { id_cuestionario: id }
|
||||
where: { id_cuestionario: id },
|
||||
relations: ['evento'] // Incluir la relación con el evento
|
||||
});
|
||||
|
||||
if (!cuestionario) {
|
||||
@@ -294,6 +332,13 @@ export class CuestionarioService {
|
||||
id_tipo_cuestionario: tipoCuestionario.id_tipo_cuestionario,
|
||||
tipo_cuestionario: tipoCuestionario.tipo_cuestionario
|
||||
},
|
||||
evento: cuestionario.evento ? {
|
||||
id_evento: cuestionario.evento.id_evento,
|
||||
nombre_evento: cuestionario.evento.nombre_evento,
|
||||
tipo_evento: cuestionario.evento.tipo_evento,
|
||||
fecha_inicio: cuestionario.evento.fecha_inicio ? cuestionario.evento.fecha_inicio.toISOString() : null,
|
||||
fecha_fin: cuestionario.evento.fecha_fin ? cuestionario.evento.fecha_fin.toISOString() : null
|
||||
} : null,
|
||||
cuestionario: {
|
||||
id_cuestionario: cuestionario.id_cuestionario,
|
||||
nombre_form: cuestionario.nombre_form,
|
||||
@@ -304,13 +349,43 @@ export class CuestionarioService {
|
||||
fecha_fin: cuestionario.fecha_fin ? cuestionario.fecha_fin.toISOString() : null,
|
||||
id_cuestionario_original: cuestionario.id_cuestionario_original,
|
||||
id_tipo_cuestionario: cuestionario.id_tipo_cuestionario,
|
||||
id_evento: cuestionario.id_evento || null,
|
||||
secciones: seccionesFormateadas
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
update(id: number, updateCuestionarioDto: UpdateCuestionarioDto) {
|
||||
return this.cuestionarioRepository.update(id, updateCuestionarioDto);
|
||||
async update(id: number, updateCuestionarioDto: UpdateCuestionarioDto) {
|
||||
// Si el DTO incluye el campo "evento" (string), debemos procesarlo aparte
|
||||
if (updateCuestionarioDto.evento) {
|
||||
// Buscar o crear evento
|
||||
let evento = await this.eventoRepository.findOne({
|
||||
where: { nombre_evento: updateCuestionarioDto.evento }
|
||||
});
|
||||
|
||||
if (!evento) {
|
||||
// Crear el evento
|
||||
const nuevoEvento = {
|
||||
nombre_evento: updateCuestionarioDto.evento,
|
||||
tipo_evento: 'Predeterminado',
|
||||
fecha_inicio: new Date(),
|
||||
fecha_fin: new Date(Date.now() + 86400000)
|
||||
};
|
||||
|
||||
evento = await this.eventoRepository.save(nuevoEvento);
|
||||
}
|
||||
|
||||
// Asignar el ID del evento al DTO de actualización
|
||||
updateCuestionarioDto.id_evento = evento.id_evento;
|
||||
|
||||
// Eliminar la propiedad evento para evitar conflictos
|
||||
delete updateCuestionarioDto.evento;
|
||||
}
|
||||
|
||||
// Preparar los datos para la actualización
|
||||
const updateData: any = { ...updateCuestionarioDto };
|
||||
|
||||
return this.cuestionarioRepository.update(id, updateData);
|
||||
}
|
||||
|
||||
remove(id: number) {
|
||||
|
||||
@@ -1,28 +1,66 @@
|
||||
import { CreateSeccionDto } from '../../seccion/dto/create-seccion.dto';
|
||||
import { IsArray, IsDateString, IsNotEmpty, IsNumber, IsOptional, IsString, ValidateNested } from 'class-validator';
|
||||
import { Type } from 'class-transformer';
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
|
||||
export class CreateCuestionarioDto {
|
||||
@ApiProperty({
|
||||
description: 'Nombre del formulario',
|
||||
example: 'Registro para la Feria de la Sexualidad - FES Acatlán'
|
||||
})
|
||||
@IsNotEmpty()
|
||||
@IsString()
|
||||
nombre_form: string;
|
||||
|
||||
@ApiProperty({
|
||||
description: 'Descripción del formulario',
|
||||
example: 'Formulario de registro para la feria...',
|
||||
required: false
|
||||
})
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
descripcion?: string;
|
||||
|
||||
@ApiProperty({
|
||||
description: 'Fecha de inicio',
|
||||
example: '2025-03-26T00:00:00',
|
||||
required: false
|
||||
})
|
||||
@IsOptional()
|
||||
@IsDateString()
|
||||
fecha_inicio?: Date;
|
||||
|
||||
@ApiProperty({
|
||||
description: 'Fecha de fin',
|
||||
example: '2025-03-31T23:59:59',
|
||||
required: false
|
||||
})
|
||||
@IsOptional()
|
||||
@IsDateString()
|
||||
fecha_fin?: Date;
|
||||
|
||||
@ApiProperty({
|
||||
description: 'ID del tipo de cuestionario',
|
||||
example: 1
|
||||
})
|
||||
@IsNotEmpty()
|
||||
@IsNumber()
|
||||
id_tipo_cuestionario: number;
|
||||
|
||||
@ApiProperty({
|
||||
description: 'Nombre del evento asociado',
|
||||
example: 'Feria de la Sexualidad',
|
||||
required: false
|
||||
})
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
evento?: string;
|
||||
|
||||
@ApiProperty({
|
||||
description: 'Secciones del cuestionario',
|
||||
type: [CreateSeccionDto],
|
||||
required: false
|
||||
})
|
||||
@IsOptional()
|
||||
@IsArray()
|
||||
@ValidateNested({ each: true })
|
||||
|
||||
@@ -1,4 +1,15 @@
|
||||
import { PartialType } from '@nestjs/mapped-types';
|
||||
import { CreateCuestionarioDto } from './create-cuestionario.dto';
|
||||
import { IsNumber, IsOptional } from 'class-validator';
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
|
||||
export class UpdateCuestionarioDto extends PartialType(CreateCuestionarioDto) {}
|
||||
export class UpdateCuestionarioDto extends PartialType(CreateCuestionarioDto) {
|
||||
@ApiProperty({
|
||||
description: 'ID del evento asociado',
|
||||
example: 1,
|
||||
required: false
|
||||
})
|
||||
@IsOptional()
|
||||
@IsNumber()
|
||||
id_evento?: number;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { CuestionarioSeccion } from 'src/cuestionario_seccion/entities/cuestionario_seccion.entity';
|
||||
import { Evento } from 'src/evento/evento.entity';
|
||||
import { TipoCuestionario } from 'src/tipo_cuestionario/entities/tipo_cuestionario.entity';
|
||||
import { Entity, PrimaryGeneratedColumn, Column, OneToMany, ManyToMany, ManyToOne } from 'typeorm';
|
||||
import { Entity, PrimaryGeneratedColumn, Column, OneToMany, ManyToMany, ManyToOne, JoinColumn } from 'typeorm';
|
||||
|
||||
|
||||
|
||||
@@ -39,4 +40,11 @@ export class Cuestionario {
|
||||
|
||||
@ManyToOne(()=> Cuestionario)
|
||||
cuestionarioOriginal: Cuestionario;
|
||||
|
||||
@Column({ type: 'int', nullable: true })
|
||||
id_evento: number;
|
||||
|
||||
@ManyToOne(() => Evento)
|
||||
@JoinColumn({ name: 'id_evento' })
|
||||
evento: Evento;
|
||||
}
|
||||
|
||||
@@ -157,17 +157,15 @@ export class CuestionarioRespondidoService {
|
||||
}
|
||||
|
||||
async findOne(id: number) {
|
||||
// Obtener cuestionario respondido con sus relaciones básicas
|
||||
const cuestionarioRespondido = await this.cuestionarioRespondidoRepository.findOne({
|
||||
where: { idCuestionarioRespondido: id },
|
||||
relations: [
|
||||
'participante',
|
||||
'cuestionario',
|
||||
'respuestasAbiertas',
|
||||
'participante',
|
||||
'cuestionario',
|
||||
'respuestasAbiertas',
|
||||
'respuestasAbiertas.pregunta',
|
||||
'respuestasCerradas',
|
||||
'respuestasCerradas.preguntaOpcion',
|
||||
'respuestasCerradas.preguntaOpcion.opcion',
|
||||
'respuestasCerradas.preguntaOpcion.pregunta'
|
||||
'respuestasCerradas'
|
||||
]
|
||||
});
|
||||
|
||||
@@ -175,7 +173,48 @@ export class CuestionarioRespondidoService {
|
||||
throw new NotFoundException(`Cuestionario respondido con ID ${id} no encontrado`);
|
||||
}
|
||||
|
||||
return cuestionarioRespondido;
|
||||
// Obtener directamente los datos de respuestas cerradas desde la base de datos
|
||||
// usando una consulta SQL directa
|
||||
const respuestasCerradas = await this.dataSource.query(`
|
||||
SELECT
|
||||
rpc.idRespuestaParticipanteCerrada,
|
||||
rpc.id_pregunta_opcion,
|
||||
po.id_pregunta,
|
||||
p.texto_pregunta,
|
||||
p.id_tipo_pregunta,
|
||||
o.id_opcion,
|
||||
o.opcion
|
||||
FROM respuesta_participante_cerrada rpc
|
||||
LEFT JOIN pregunta_opcion po ON rpc.id_pregunta_opcion = po.id_pregunta_opcion
|
||||
LEFT JOIN pregunta p ON po.id_pregunta = p.id_pregunta
|
||||
LEFT JOIN opcion o ON po.id_opcion = o.id_opcion
|
||||
WHERE rpc.id_cuestionario_respondido = ?
|
||||
`, [id]);
|
||||
|
||||
console.log('Respuestas cerradas SQL:', JSON.stringify(respuestasCerradas, null, 2));
|
||||
|
||||
// Transformar las respuestas cerradas al formato deseado
|
||||
const respuestasCerradasFormateadas = respuestasCerradas.map(respuesta => ({
|
||||
idRespuestaParticipanteCerrada: respuesta.idRespuestaParticipanteCerrada,
|
||||
id_pregunta_opcion: respuesta.id_pregunta_opcion,
|
||||
pregunta: {
|
||||
id_pregunta: respuesta.id_pregunta,
|
||||
texto_pregunta: respuesta.texto_pregunta,
|
||||
id_tipo_pregunta: respuesta.id_tipo_pregunta
|
||||
},
|
||||
opcion: {
|
||||
id_opcion: respuesta.id_opcion,
|
||||
opcion: respuesta.opcion
|
||||
}
|
||||
}));
|
||||
|
||||
// Crear el objeto de respuesta con el formato deseado
|
||||
const resultado = {
|
||||
...cuestionarioRespondido,
|
||||
respuestasCerradas: respuestasCerradasFormateadas
|
||||
};
|
||||
|
||||
return resultado;
|
||||
}
|
||||
|
||||
update(id: number, updateCuestionarioRespondidoDto: UpdateCuestionarioRespondidoDto) {
|
||||
|
||||
@@ -4,6 +4,7 @@ import { InjectRepository } from '@nestjs/typeorm';
|
||||
import { Repository } from 'typeorm';
|
||||
import { CreateQrDto } from './dto/create-qr.dto';
|
||||
import { UpdateQrDto } from './dto/update.qr.dto';
|
||||
// @ts-ignore
|
||||
import * as QRCode from 'qrcode';
|
||||
|
||||
@Injectable()
|
||||
|
||||
@@ -5,6 +5,7 @@ export const feriaSexualidad = {
|
||||
fecha_inicio: '2025-03-07T00:00:01',
|
||||
fecha_fin: '2025-03-18T23:59:59',
|
||||
id_tipo_cuestionario: 1,
|
||||
evento: 'Feria de la Sexualidad',
|
||||
secciones: [
|
||||
{
|
||||
titulo: 'Información Personal',
|
||||
|
||||
Reference in New Issue
Block a user