255 lines
7.8 KiB
TypeScript
255 lines
7.8 KiB
TypeScript
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<Pregunta>,
|
|
@InjectRepository(TipoPregunta)
|
|
private tipoPreguntaRepository: Repository<TipoPregunta>,
|
|
@InjectRepository(Opcion)
|
|
private opcionRepository: Repository<Opcion>,
|
|
@InjectRepository(PreguntaOpcion)
|
|
private preguntaOpcionRepository: Repository<PreguntaOpcion>,
|
|
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;
|
|
|
|
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;
|
|
|
|
// 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();
|
|
}
|
|
}
|
|
}
|