import { Injectable, NotFoundException } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { Repository, DataSource } from 'typeorm'; import { CreatePreguntaDto, OpcionDto } from './dto/create-pregunta.dto'; import { UpdatePreguntaDto } from './dto/update-pregunta.dto'; import { Pregunta } from './entities/pregunta.entity'; import { TipoPregunta } from '../tipo_pregunta/entities/tipo_pregunta.entity'; import { Opcion } from '../opcion/entities/opcion.entity'; import { PreguntaOpcion } from '../pregunta_opcion/entities/pregunta_opcion.entity'; @Injectable() export class PreguntaService { constructor( @InjectRepository(Pregunta) private preguntaRepository: Repository, @InjectRepository(TipoPregunta) private tipoPreguntaRepository: Repository, @InjectRepository(Opcion) private opcionRepository: Repository, @InjectRepository(PreguntaOpcion) private preguntaOpcionRepository: Repository, private dataSource: DataSource ) {} async create(createPreguntaDto: CreatePreguntaDto) { const queryRunner = this.dataSource.createQueryRunner(); await queryRunner.connect(); await queryRunner.startTransaction(); try { // Obtener el tipo de pregunta por su nombre const tipoPregunta = await this.tipoPreguntaRepository.findOne({ where: { tipo_pregunta: createPreguntaDto.tipo } }); if (!tipoPregunta) { throw new Error(`Tipo de pregunta '${createPreguntaDto.tipo}' no encontrado`); } // Crear pregunta const pregunta = new Pregunta(); pregunta.pregunta = createPreguntaDto.titulo; pregunta.obligatoria = createPreguntaDto.obligatoria || false; pregunta.id_tipo_pregunta = tipoPregunta.id_tipo; pregunta.id_opcion_dependiente = createPreguntaDto.id_opcion_dependiente || undefined; pregunta.contador_opcion = createPreguntaDto.opciones?.length || 0; pregunta.validacion = createPreguntaDto.validacion || undefined; const savedPregunta = await queryRunner.manager.save(pregunta); // Crear opciones para preguntas de tipo multiple/radio if (createPreguntaDto.opciones && createPreguntaDto.opciones.length > 0) { await this.createOpciones( queryRunner, savedPregunta.id_pregunta, createPreguntaDto.opciones ); } await queryRunner.commitTransaction(); return { success: true, pregunta: savedPregunta }; } catch (error) { await queryRunner.rollbackTransaction(); throw error; } finally { await queryRunner.release(); } } private async createOpciones( queryRunner: any, preguntaId: number, opciones: OpcionDto[] ) { for (let i = 0; i < opciones.length; i++) { const opcionDto = opciones[i]; // Crear opción const opcion = new Opcion(); opcion.opcion = opcionDto.valor; const savedOpcion = await queryRunner.manager.save(opcion); // Vincular opción con pregunta const preguntaOpcion = new PreguntaOpcion(); preguntaOpcion.id_pregunta = preguntaId; preguntaOpcion.opcion = savedOpcion; preguntaOpcion.posicion = i + 1; await queryRunner.manager.save(preguntaOpcion); } } async findAll() { return this.preguntaRepository.find(); } async findOne(id: number) { const pregunta = await this.preguntaRepository.findOne({ where: { id_pregunta: id } }); if (!pregunta) { throw new NotFoundException(`Pregunta con ID ${id} no encontrada`); } return pregunta; } async findWithOptions(id: number) { const pregunta = await this.preguntaRepository.findOne({ where: { id_pregunta: id }, relations: ['tipoPregunta'] }); if (!pregunta) { throw new NotFoundException(`Pregunta con ID ${id} no encontrada`); } // Obtener las opciones para esta pregunta const preguntaOpciones = await this.preguntaOpcionRepository.find({ where: { id_pregunta: id }, relations: ['opcion'], order: { posicion: 'ASC' } }); const opciones = preguntaOpciones.map(po => ({ id: po.opcion.id_opcion, valor: po.opcion.opcion, posicion: po.posicion })); return { ...pregunta, tipo: pregunta.tipoPregunta?.tipo_pregunta, opciones }; } async update(id: number, updatePreguntaDto: UpdatePreguntaDto) { const queryRunner = this.dataSource.createQueryRunner(); await queryRunner.connect(); await queryRunner.startTransaction(); try { const pregunta = await this.preguntaRepository.findOne({ where: { id_pregunta: id } }); if (!pregunta) { throw new NotFoundException(`Pregunta con ID ${id} no encontrada`); } // Actualizar los campos básicos de la pregunta if (updatePreguntaDto.titulo) pregunta.pregunta = updatePreguntaDto.titulo; if (updatePreguntaDto.obligatoria !== undefined) pregunta.obligatoria = updatePreguntaDto.obligatoria; if (updatePreguntaDto.id_opcion_dependiente !== undefined) pregunta.id_opcion_dependiente = updatePreguntaDto.id_opcion_dependiente; if (updatePreguntaDto.validacion !== undefined) pregunta.validacion = updatePreguntaDto.validacion; // Si se proporciona un nuevo tipo de pregunta, actualizarlo if (updatePreguntaDto.tipo) { const tipoPregunta = await this.tipoPreguntaRepository.findOne({ where: { tipo_pregunta: updatePreguntaDto.tipo } }); if (!tipoPregunta) { throw new Error(`Tipo de pregunta '${updatePreguntaDto.tipo}' no encontrado`); } pregunta.id_tipo_pregunta = tipoPregunta.id_tipo; } // Actualizar la pregunta const updatedPregunta = await queryRunner.manager.save(pregunta); // Si se proporcionan nuevas opciones, actualizarlas if (updatePreguntaDto.opciones && updatePreguntaDto.opciones.length > 0) { // Eliminar las opciones existentes const existingOptions = await this.preguntaOpcionRepository.find({ where: { id_pregunta: id } }); for (const option of existingOptions) { await queryRunner.manager.remove(option); } // Crear las nuevas opciones await this.createOpciones( queryRunner, id, updatePreguntaDto.opciones ); // Actualizar el contador de opciones updatedPregunta.contador_opcion = updatePreguntaDto.opciones.length; await queryRunner.manager.save(updatedPregunta); } await queryRunner.commitTransaction(); return { success: true, pregunta: updatedPregunta }; } catch (error) { await queryRunner.rollbackTransaction(); throw error; } finally { await queryRunner.release(); } } async remove(id: number) { const queryRunner = this.dataSource.createQueryRunner(); await queryRunner.connect(); await queryRunner.startTransaction(); try { const pregunta = await this.preguntaRepository.findOne({ where: { id_pregunta: id } }); if (!pregunta) { throw new NotFoundException(`Pregunta con ID ${id} no encontrada`); } // Eliminar las relaciones con opciones const preguntaOpciones = await this.preguntaOpcionRepository.find({ where: { id_pregunta: id } }); for (const po of preguntaOpciones) { await queryRunner.manager.remove(po); } // Eliminar la pregunta await queryRunner.manager.remove(pregunta); await queryRunner.commitTransaction(); return { success: true, message: `Pregunta con ID ${id} eliminada correctamente` }; } catch (error) { await queryRunner.rollbackTransaction(); throw error; } finally { await queryRunner.release(); } } }