Merge remote-tracking branch 'origin/santiago' into Emilio

This commit is contained in:
2025-04-02 00:26:29 -06:00
45 changed files with 1452 additions and 0 deletions
+128
View File
@@ -0,0 +1,128 @@
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { AdminModule } from './admin/admin.module';
import {TypeOrmModule } from '@nestjs/typeorm'
import { PostsModule } from './posts/posts.module';
import { TipoUserModule } from './tipo_user/tipo_user.module';
import { EventoModule } from './evento/evento.module';
import { ParticipanteModule } from './participante/participante.module';
import { QrModule } from './qr/qr.module';
import { AdministradorModule } from './administrador/administrador.module';
import { AsistenciaModule } from './asistencia/asistencia.module';
import { ParticipanteEventoModule } from './participante_evento/participante_evento.module';
@Module({
imports: [
TypeOrmModule.forRoot({
type: 'mysql',
host: 'localhost',
port: 3306, //3306
username: 'root',
password: 'admin', //admin
database: 'nestdb',
entities: [__dirname + '/**/*.entity{.ts,.js}'],
synchronize: true,
//extra
retryAttempts: 10, // Intentos para reconectar
retryDelay: 3000, // Tiempo entre reintentos
}),
AdminModule,
PostsModule,
EventoModule,
TipoUserModule,
ParticipanteModule,
QrModule,
AdministradorModule,
AsistenciaModule,
ParticipanteEventoModule,
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
//
{
"name": "nestjs-mysql",
"version": "0.0.1",
"description": "",
"author": "",
"private": true,
"license": "UNLICENSED",
"scripts": {
"build": "nest build",
"format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
"start": "nest start",
"start:dev": "nest start --watch",
"start:debug": "nest start --debug --watch",
"start:prod": "node dist/main",
"lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix",
"test": "jest",
"test:watch": "jest --watch",
"test:cov": "jest --coverage",
"test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
"test:e2e": "jest --config ./test/jest-e2e.json"
},
"dependencies": {
"@nestjs/common": "^11.0.1",
"@nestjs/core": "^11.0.1",
"@nestjs/platform-express": "^11.0.1",
"@nestjs/swagger": "^11.1.0",
"@nestjs/typeorm": "^11.0.0",
"class-transformer": "^0.5.1",
"class-validator": "^0.14.1",
"jsonwebtoken": "^9.0.2",
"mysql2": "^3.13.0",
"reflect-metadata": "^0.2.2",
"rxjs": "^7.8.1",
"swagger-ui-express": "^5.0.1",
"typeorm": "^0.3.21"
},
"devDependencies": {
"@eslint/eslintrc": "^3.2.0",
"@eslint/js": "^9.18.0",
"@nestjs/cli": "^11.0.0",
"@nestjs/schematics": "^11.0.0",
"@nestjs/testing": "^11.0.1",
"@swc/cli": "^0.6.0",
"@swc/core": "^1.10.7",
"@types/express": "^5.0.0",
"@types/jest": "^29.5.14",
"@types/node": "^22.10.7",
"@types/supertest": "^6.0.2",
"eslint": "^9.18.0",
"eslint-config-prettier": "^10.0.1",
"eslint-plugin-prettier": "^5.2.2",
"globals": "^16.0.0",
"jest": "^29.7.0",
"prettier": "^3.4.2",
"source-map-support": "^0.5.21",
"supertest": "^7.0.0",
"ts-jest": "^29.2.5",
"ts-loader": "^9.5.2",
"ts-node": "^10.9.2",
"tsconfig-paths": "^4.2.0",
"typescript": "^5.7.3",
"typescript-eslint": "^8.20.0"
},
"jest": {
"moduleFileExtensions": [
"js",
"json",
"ts"
],
"rootDir": "src",
"testRegex": ".*\\.spec\\.ts$",
"transform": {
"^.+\\.(t|j)s$": "ts-jest"
},
"collectCoverageFrom": [
"**/*.(t|j)s"
],
"coverageDirectory": "../coverage",
"testEnvironment": "node"
}
}
@@ -0,0 +1,57 @@
import { Body, Controller, Delete, Get, Param, ParseIntPipe, Patch, Post } from '@nestjs/common';
import { AdministradorService } from './administrador.service';
import { Administrador } from './administrador.entity';
import { CreateAdministradorDto } from './dto/create-administrador.dto';
import { UpdateAdministradorDto } from './dto/update.administrador.dto';
import { ApiTags, ApiOperation, ApiResponse, ApiParam, ApiBody } from '@nestjs/swagger';
@ApiTags('Administradores') // Agrupa los endpoints en Swagger
@Controller('administrador')
export class AdministradorController {
constructor(private administradorService: AdministradorService) {}
@Get()
@ApiOperation({ summary: 'Obtener todos los administradores' })
@ApiResponse({ status: 200, description: 'Lista de administradores obtenida correctamente.' })
getAdministradores(): Promise<Administrador[]> {
return this.administradorService.getAdministradores();
}
@Get(':id')
@ApiOperation({ summary: 'Obtener un administrador por ID' })
@ApiParam({ name: 'id', description: 'ID del administrador', example: 1 })
@ApiResponse({ status: 200, description: 'Administrador obtenido correctamente.' })
@ApiResponse({ status: 404, description: 'Administrador no encontrado.' })
getAdministrador(@Param('id', ParseIntPipe) id: number) {
return this.administradorService.getAdministrador(id)
}
@Post()
@ApiOperation({ summary: 'Registrar un nuevo administrador' })
@ApiBody({
description: 'Datos del administrador a registrar',
schema: {
type: 'object',
properties: {
id_tipo_user: { type: 'integer', example: 1 }
}
}
})
@ApiResponse({ status: 201, description: 'Administrador registrado exitosamente.' })
@ApiResponse({ status: 400, description: 'Datos inválidos.' })
createAdministrador(@Body() newAdministrador: CreateAdministradorDto) {
return this.administradorService.createAdministrador(newAdministrador)
}
@Delete(':id')
deleteAdministrador(@Param('id', ParseIntPipe) id: number) {
return this.administradorService.deleteAdministrador(id)
}
@Patch(':id')
updateAdministrador(@Param('id', ParseIntPipe) id: number, @Body() administrador: UpdateAdministradorDto) {
return this.administradorService.updateAdministrador(id, administrador)
}
}
+28
View File
@@ -0,0 +1,28 @@
import { TipoUser } from "src/tipo_user/tipo_user.entity";
import { Column, Entity, ManyToOne, PrimaryGeneratedColumn } from "typeorm";
@Entity()
export class Administrador {
@PrimaryGeneratedColumn()
id_admnistrador: number
/*
@ManyToOne(() => TipoUser, (tipoUser) => tipoUser.administradores)
@JoinColumn({ name: "id_tipo_user" })
tipoUser: TipoUser;
*/
//Relacion con tipo_user
@Column()
id_tipo_user: number
@ManyToOne(() => TipoUser, (tipoUser) => tipoUser.administrador)
tipoUser: TipoUser[]
/*
@OneToMany(() => Evento, (evento) => evento.administrador)
eventos: Evento[];
@OneToMany(() => Asistencia, (asistencia) => asistencia.administrador)
asistencias: Asistencia[];
*/
}
+13
View File
@@ -0,0 +1,13 @@
import { Module } from '@nestjs/common';
import { AdministradorService } from './administrador.service';
import { AdministradorController } from './administrador.controller';
import { TypeOrmModule } from '@nestjs/typeorm';
import { Administrador } from './administrador.entity';
@Module({
imports: [TypeOrmModule.forFeature([Administrador])],
controllers: [AdministradorController],
providers: [AdministradorService],
exports: [AdministradorService],
})
export class AdministradorModule {}
@@ -0,0 +1,79 @@
import { HttpException, HttpStatus, Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Administrador } from './administrador.entity';
import { Repository } from 'typeorm';
import { CreateAdministradorDto } from './dto/create-administrador.dto';
import { UpdateAdministradorDto } from './dto/update.administrador.dto';
@Injectable()
export class AdministradorService {
constructor(
@InjectRepository(Administrador) private administradorRepository: Repository<Administrador>
) {}
async createAdministrador(administrador: CreateAdministradorDto) {
//revisar el where
const administradorFound = await this.administradorRepository.findOne({
where: {
id_admnistrador: administrador.id_tipo_user
}
})
if (administradorFound) {
return new HttpException('Administrador already exists', HttpStatus.CONFLICT)
}
//Falta regresar el return
//return this.administradorRepository.save(administradorFound)
}
getAdministradores() {
return this.administradorRepository.find({
relations: ['tipoUser']
})
}
async getAdministrador(id_admnistrador: number) {
const administradorFound = await this.administradorRepository.findOne({
where: {
id_admnistrador
},
relations: ['tipoUser']
})
if (!Administrador) {
return new HttpException('User not found', HttpStatus.NOT_FOUND);
}
return administradorFound
}
async deleteAdministrador(id_admnistrador: number) {
const result = await this.administradorRepository.delete({ id_admnistrador })
if (result.affected === 0) {
return new HttpException('User not found', HttpStatus.NOT_FOUND);
}
return result
}
async updateAdministrador(id_admnistrador: number, administrador: UpdateAdministradorDto) {
const administradorFound = await this.administradorRepository.findOne({
where: {
id_admnistrador
}
})
if (!administradorFound) {
return new HttpException('User not found', HttpStatus.NOT_FOUND)
}
const updateAdministrador = Object.assign(administradorFound, administrador)
return this.administradorRepository.save(updateAdministrador)
}
}
@@ -0,0 +1,3 @@
export class CreateAdministradorDto {
id_tipo_user: number
}
@@ -0,0 +1,3 @@
export class UpdateAdministradorDto {
id_tipo_user?: number
}
+37
View File
@@ -0,0 +1,37 @@
import { Body, Controller, Delete, Get, Param, ParseIntPipe, Patch, Post } from '@nestjs/common';
import { AsistenciaService } from './asistencia.service';
import { Asistencia } from './asistencia.entity';
import { CreateAsistenciaDto } from './dto/create-asistencia.dto';
import { UpdateAsistenciaDto } from './dto/update.asistencia.dto';
@Controller('asistencia')
export class AsistenciaController {
constructor(private asistenciaService: AsistenciaService) {}
@Get()
getAsistencias(): Promise<Asistencia[]> {
return this.asistenciaService.getAsistencias()
}
@Get(':id')
getAsistencia(@Param('id', ParseIntPipe) id: number) {
return this.asistenciaService.getAsistencia(id)
}
@Post()
createAsistencia(@Body() newAsistencia: CreateAsistenciaDto) {
return this.asistenciaService.createAsistencia(newAsistencia)
}
@Delete()
deleteAsistencia(@Param('id', ParseIntPipe) id: number) {
return this.asistenciaService.deleteAsistencia(id)
}
@Patch(':id')
updateAsistencia(@Param('id', ParseIntPipe) id: number, @Body() asistencia: UpdateAsistenciaDto) {
return this.asistenciaService.updateAsistencia(id, asistencia)
}
}
+41
View File
@@ -0,0 +1,41 @@
import { Column, Entity, PrimaryGeneratedColumn } from "typeorm";
@Entity()
export class Asistencia {
@PrimaryGeneratedColumn()
id_asistecia: number
//({type: 'datetime', default: () => 'CURRENT_TIMESTAMP' }
@Column({type: 'datetime', default: () => 'CURRENT_TIMESTAMP'})
fecha_asistencia: Date
@Column()
metodo: boolean
@Column()
estado: boolean
//relaciones con las otras tablas
@Column()
id_participante: number
@Column()
id_evento: number
@Column()
id_administrador: number
/*
@ManyToOne(() => Administrador, (admin) => admin.asistencias)
@JoinColumn({ name: "id_administrador" })
administrador: Administrador;
@ManyToOne(() => Evento, (evento) => evento.asistencias)
@JoinColumn({ name: "id_evento" })
evento: Evento;
@ManyToOne(() => Participante, (participante) => participante.asistencias)
@JoinColumn({ name: "id_participante" })
participante: Participante;
*/
}
+12
View File
@@ -0,0 +1,12 @@
import { Module } from '@nestjs/common';
import { AsistenciaService } from './asistencia.service';
import { AsistenciaController } from './asistencia.controller';
import { TypeOrmModule } from '@nestjs/typeorm';
import { Asistencia } from './asistencia.entity';
@Module({
imports: [TypeOrmModule.forFeature([Asistencia])],
controllers: [AsistenciaController],
providers: [AsistenciaService]
})
export class AsistenciaModule {}
+77
View File
@@ -0,0 +1,77 @@
import { HttpException, HttpStatus, Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Asistencia } from './asistencia.entity';
import { Repository } from 'typeorm';
import { CreateAsistenciaDto } from './dto/create-asistencia.dto';
import { UpdateAsistenciaDto } from './dto/update.asistencia.dto';
@Injectable()
export class AsistenciaService {
constructor(
@InjectRepository(Asistencia) private asistenciaRepository: Repository<Asistencia>
) {}
async createAsistencia(asistencia: CreateAsistenciaDto) {
const asistenciaFound = await this.asistenciaRepository.findOne({
where: {
fecha_asistencia: asistencia.fecha_asistencia,
metodo: asistencia.metodo,
estado: asistencia.estdao
}
})
if (asistenciaFound) {
return new HttpException('User already exists', HttpStatus.CONFLICT)
}
return this.asistenciaRepository.save(asistencia)
}
getAsistencias() {
return this.asistenciaRepository.find({})
}
async getAsistencia(id_asistecia: number) {
const asistenciaFound = await this.asistenciaRepository.findOne({
where: {
id_asistecia
}
})
if (!asistenciaFound) {
return new HttpException('User not found', HttpStatus.NOT_FOUND);
}
return asistenciaFound
}
async deleteAsistencia(id_asistecia: number) {
const result = await this.asistenciaRepository.delete({ id_asistecia })
if (result.affected === 0) {
return new HttpException('User not found', HttpStatus.NOT_FOUND);
}
return result
}
async updateAsistencia(id_asistecia: number, asistencia: UpdateAsistenciaDto) {
const asistenciaFound = await this.asistenciaRepository.findOne({
where: {
id_asistecia
}
})
if (!asistenciaFound) {
return new HttpException('User not found', HttpStatus.NOT_FOUND)
}
const updateAsistencia = Object.assign(asistenciaFound, asistencia)
return this.asistenciaRepository.save(updateAsistencia)
}
}
@@ -0,0 +1,5 @@
export class CreateAsistenciaDto {
fecha_asistencia: Date
metodo: boolean
estdao: boolean
}
@@ -0,0 +1,5 @@
export class UpdateAsistenciaDto {
fecha_asistencia?: Date
metodo?: boolean
estado?: boolean
}
+12
View File
@@ -0,0 +1,12 @@
import { Module } from '@nestjs/common';
import { SwaggerModule } from '@nestjs/swagger';
import { swaggerConfig } from './swagger.config';
import { INestApplication } from '@nestjs/common';
@Module({})
export class DocsModule {
static setupSwagger(app: INestApplication) {
const document = SwaggerModule.createDocument(app, swaggerConfig);
SwaggerModule.setup('api-docs', app, document);
}
}
+11
View File
@@ -0,0 +1,11 @@
import { DocumentBuilder } from '@nestjs/swagger';
export const swaggerConfig = new DocumentBuilder()
.setTitle('Sistema de Registro de Usuarios y Eventos')
.setDescription('API para gestionar usuarios, eventos, asistencia y códigos QR')
.setVersion('1.0')
.addTag('Usuarios')
.addTag('Eventos')
.addTag('Asistencia')
.addTag('QR')
.build();
+11
View File
@@ -0,0 +1,11 @@
export class CreateEventoDto {
tipo_evento: string;
nombre_evento: string;
fecha_inicio: Date;
fecha_fin: Date;
//agregar el id del administrador
}
+6
View File
@@ -0,0 +1,6 @@
export class UpdateEventoDto {
tipo_evento?: string
nombre_evento: string
fecha_inicio?: Date
fecha_fin?: Date
}
+37
View File
@@ -0,0 +1,37 @@
import { Body, Controller, Delete, Get, Param, ParseIntPipe, Patch, Post } from '@nestjs/common';
import { EventoService } from './evento.service';
import { Evento } from './evento.entity';
import { CreateEventoDto } from './dto/create-evento.dto';
import { UpdateEventoDto } from './dto/update.evento.dto';
@Controller('evento')
export class EventoController {
constructor(private eventoService: EventoService) {}
@Get()
getEventos(): Promise<Evento[]> {
return this.eventoService.getEventos()
}
@Get(':id')
getEvento(@Param('id', ParseIntPipe) id: number) {
return this.eventoService.getEvento(id)
}
@Post()
createEvento(@Body() newEvento: CreateEventoDto) {
return this.eventoService.createEvento(newEvento)
}
@Delete(':id')
deleteEvento(@Param('id', ParseIntPipe) id: number) {
return this.eventoService.deleteEvento(id)
}
//@Param(':id', ParseIntPipe) id: number, @Body() tipoUser: UpdateTipoUserDto
@Patch()
updateEvento(@Param(':id', ParseIntPipe) id: number, @Body() evento: UpdateEventoDto) {
return this.eventoService.updateEvento(id, evento)
}
}
+38
View File
@@ -0,0 +1,38 @@
import { ParticipanteEvento } from "src/participante_evento/participante_evento.entity";
import { Column, Entity, OneToMany, PrimaryGeneratedColumn } from "typeorm";
@Entity()
export class Evento {
@PrimaryGeneratedColumn()
id_evento: number
@Column()
tipo_evento: string
@Column()
nombre_evento: string
@Column({type: 'datetime', default: () => 'CURRENT_TIMESTAMP' })
fecha_inicio: Date
@Column({type: 'datetime', default: () => 'CURRENT_TIMESTAMP' })
fecha_fin: Date
/* falta hacer la relacion
@Column()
id_administrador: number
@ManyToOne(() => Administrador, (admin) => admin.eventos)
@JoinColumn({ name: "id_administrador" })
administrador: Administrador;
@OneToMany(() => ParticipanteEvento, (pe) => pe.evento)
participantes: ParticipanteEvento[];
@OneToMany(() => Asistencia, (asistencia) => asistencia.evento)
asistencias: Asistencia[];
*/
@OneToMany(() => ParticipanteEvento, (participanteEvento) => participanteEvento.evento)
participantes: ParticipanteEvento[];
}
+12
View File
@@ -0,0 +1,12 @@
import { Module } from '@nestjs/common';
import { EventoService } from './evento.service';
import { EventoController } from './evento.controller';
import { TypeOrmModule } from '@nestjs/typeorm';
import { Evento } from './evento.entity';
@Module({
imports: [TypeOrmModule.forFeature([Evento])],
controllers: [EventoController],
providers: [EventoService]
})
export class EventoModule {}
+73
View File
@@ -0,0 +1,73 @@
import { HttpException, HttpStatus, Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { Evento } from './evento.entity';
import { CreateEventoDto } from './dto/create-evento.dto';
import { UpdateEventoDto } from './dto/update.evento.dto';
@Injectable()
export class EventoService {
constructor(
@InjectRepository(Evento) private eventoRepository: Repository<Evento>,
) {}
async createEvento(evento: CreateEventoDto) {
const eventoFound = await this.eventoRepository.findOne({
where: {
nombre_evento: evento.nombre_evento,
tipo_evento: evento.tipo_evento
}
})
if (eventoFound)
return new HttpException('Evento already exists', HttpStatus.CONFLICT)
const createEvento = this.eventoRepository.create(evento)
return this.eventoRepository.save(createEvento)
}
getEventos() {
return this.eventoRepository.find({
relations: ['participantes']
})
}
async getEvento(id_evento: number) {
const eventoFound = await this.eventoRepository.findOne({
where: {
id_evento
},
relations: ['participantes']
})
if (!eventoFound)
return new HttpException('Evento not found', HttpStatus.NOT_FOUND);
return eventoFound
}
async deleteEvento(id_evento: number) {
const result = await this.eventoRepository.delete({ id_evento })
if (result.affected === 0) {
return new HttpException('Evento not found', HttpStatus.NOT_FOUND);
}
return result
}
async updateEvento(id_evento: number, evento: UpdateEventoDto) {
const eventoFound = await this.eventoRepository.findOne({
where: {
id_evento
}
})
if (!eventoFound)
return new HttpException('Evento not found', HttpStatus.NOT_FOUND)
const updateEvento = Object.assign(eventoFound, evento)
return this.eventoRepository.save(updateEvento)
}
}
@@ -0,0 +1,7 @@
import { IsEmail } from "class-validator";
export class CreateParticipanteDto {
@IsEmail()
correo: string
id_tipo_user: number
}
@@ -0,0 +1,3 @@
export class UpdateParticipanteDto {
correo: string
}
@@ -0,0 +1,60 @@
import { Body, Controller, Delete, Get, Param, ParseIntPipe, Patch, Post } from '@nestjs/common';
import { Participante } from './participante.entity';
import { ParticipanteService } from './participante.service';
import { CreateParticipanteDto } from './dto/create-participante.dto';
import { UpdateParticipanteDto } from './dto/update.participante.dto';
import { ApiTags, ApiOperation, ApiResponse, ApiParam, ApiBody } from '@nestjs/swagger';
@ApiTags('Participantes') // Agrupa los endpoints en Swagger
@Controller('participante')
export class ParticipanteController {
constructor(private participanteService: ParticipanteService) {}
@ApiOperation({ summary: 'Obtener todos los participantes' })
@ApiResponse({ status: 200, description: 'Lista de participantes obtenida correctamente.' })
@Get()
getParticipantes(): Promise<Participante[]> {
return this.participanteService.getParticipantes()
}
@Get(':id')
@ApiOperation({ summary: 'Obtener un participante por ID' })
@ApiParam({ name: 'id', description: 'ID del participante', example: 1 })
@ApiResponse({ status: 200, description: 'Participante obtenido correctamente.' })
@ApiResponse({ status: 404, description: 'Participante no encontrado.' })
getParticipante(@Param('id', ParseIntPipe) id: number) {
return this.participanteService.getParticipante(id);
}
@Post()
@ApiOperation({ summary: 'Registrar un nuevo participante' })
@ApiBody({
description: 'Datos del participante a registrar',
schema: {
type: 'object',
properties: {
correo: { type: 'string', example: 'user@example.com' },
id_tipo_user: { type: 'integer', example: 2 }
}
}
})
@ApiResponse({ status: 201, description: 'Participante registrado exitosamente.' })
@ApiResponse({ status: 400, description: 'Datos inválidos.' })
createParticipante(@Body() newParticipante: CreateParticipanteDto) {
return this.participanteService.createParticipante(newParticipante);
}
@Delete(':id')
deleteParticipante(@Param('id', ParseIntPipe) id: number) {
return this.participanteService.deleteParticipante(id)
}
@Patch(':id')
updateParticipante(@Param('correo') id: number, @Body() participante: UpdateParticipanteDto) {
return this.participanteService.updateParticipante(id, participante);
}
}
+34
View File
@@ -0,0 +1,34 @@
import { ParticipanteEvento } from "src/participante_evento/participante_evento.entity";
import { TipoUser } from "src/tipo_user/tipo_user.entity";
import { Column, Entity, JoinColumn, ManyToOne, OneToMany, PrimaryGeneratedColumn } from "typeorm";
@Entity()
export class Participante {
@PrimaryGeneratedColumn()
id_participante: number
@Column()
correo: string
@Column()
id_tipo_user: number
//Relacion con tipo usuario
@ManyToOne(() => TipoUser, tipoUser => tipoUser.participante)
@JoinColumn({ name: 'participante_id' }) //nombre de la relacion
tipo_user: TipoUser[]
/*
@ManyToOne(() => Administrador, (admin) => admin.eventos)
@JoinColumn({ name: "id_administrador" })
administrador: Administrador;
@OneToMany(() => ParticipanteEvento, (pe) => pe.evento)
participantes: ParticipanteEvento[];
@OneToMany(() => Asistencia, (asistencia) => asistencia.evento)
asistencias: Asistencia[];
*/
}
+13
View File
@@ -0,0 +1,13 @@
import { Module } from '@nestjs/common';
import { ParticipanteService } from './participante.service';
import { ParticipanteController } from './participante.controller';
import { TypeOrmModule } from '@nestjs/typeorm';
import { Participante } from './participante.entity';
@Module({
imports: [TypeOrmModule.forFeature([Participante])],
controllers: [ParticipanteController],
providers: [ParticipanteService],
exports: [ParticipanteService],
})
export class ParticipanteModule {}
+74
View File
@@ -0,0 +1,74 @@
import { HttpException, HttpStatus, Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Participante } from './participante.entity';
import { Repository } from 'typeorm';
import { CreateParticipanteDto } from './dto/create-participante.dto';
import { UpdateAdminDto } from 'src/admin/dto/update.admin.dto';
import { UpdateParticipanteDto } from './dto/update.participante.dto';
@Injectable()
export class ParticipanteService {
constructor(
@InjectRepository(Participante) private participanteRepository: Repository<Participante>
) {}
async createParticipante(participante: CreateParticipanteDto) {
const participanteFound = await this.participanteRepository.findOne({
where: {
correo: participante.correo
}
})
if (participanteFound)
return new HttpException('Participante already exists', HttpStatus.CONFLICT)
return this.participanteRepository.save(participante)
}
getParticipantes() {
return this.participanteRepository.find({
relations: ['tipo_user']
})
}
async getParticipante(id_participante: number) {
const participanteFound = await this.participanteRepository.findOne({
where: {
id_participante
},
relations: ['tipo_user']
})
if (!participanteFound)
return new HttpException('Participante not found', HttpStatus.NOT_FOUND);
return participanteFound;
}
async deleteParticipante(id_participante: number) {
const result = await this.participanteRepository.delete({ id_participante })
if (result.affected === 0) {
return new HttpException('Participante not found', HttpStatus.NOT_FOUND);
}
return result;
}
async updateParticipante(id_participante: number, participante: UpdateParticipanteDto) {
const participanteFound = await this.participanteRepository.findOne({
where: {
id_participante
}
});
if (!participanteFound) {
return new HttpException('Participante not found', HttpStatus.NOT_FOUND)
}
const updateParticipante = Object.assign(participanteFound, participante)
return this.participanteRepository.save(updateParticipante)
}
}
@@ -0,0 +1,5 @@
export class CreateParticipanteEventoDto {
id_participante: number
id_evento: number
}
@@ -0,0 +1,6 @@
export class UpdateParticipanteEventoDto {
id_participante?: number
id_evento?: number
fecha_inscripcion?: Date
estatus?: boolean
}
@@ -0,0 +1,36 @@
import { Body, Controller, Delete, Get, Param, ParseIntPipe, Patch, Post } from '@nestjs/common';
import { ParticipanteEventoService } from './participante_evento.service';
import { ParticipanteEvento } from './participante_evento.entity';
import { CreateParticipanteEventoDto } from './dto/create-participante_evento.dto';
import { UpdateParticipanteEventoDto } from './dto/update.participante_evento.dto';
@Controller('participante-evento')
export class ParticipanteEventoController {
constructor(private participanteEventoService: ParticipanteEventoService) {}
@Get()
getParticipantesEvento(): Promise<ParticipanteEvento[]> {
return this.participanteEventoService.getParticipantesEvento()
}
@Get(':id')
getParticipanteEvento(@Param('id', ParseIntPipe) id: number) {
return this.participanteEventoService.getParticipanteEvento(id)
}
@Post()
createParticipanteEvento(@Body() newParticipanteEvento: CreateParticipanteEventoDto) {
return this.participanteEventoService.createParticipanteEvento(newParticipanteEvento)
}
@Delete(':id')
deleteParticipanteEvento(@Param('id', ParseIntPipe) id: number) {
return this.participanteEventoService.deleteParticipanteEvento(id)
}
@Patch(':id')
updateParticipanteEvento(@Param('id', ParseIntPipe) id_participante: number, id_evento: number, @Body() participanteEvento: UpdateParticipanteEventoDto) {
return this.participanteEventoService.updateParticipanteEvento(id_participante, id_evento, participanteEvento)
}
}
@@ -0,0 +1,33 @@
import { Evento } from "src/evento/evento.entity";
import { Column, Entity, JoinColumn, ManyToOne, PrimaryColumn, PrimaryGeneratedColumn } from "typeorm";
@Entity()
export class ParticipanteEvento {
@PrimaryColumn()
id_participante: number
@PrimaryColumn()
id_evento: number
@Column()
fecha_inscripcion: Date
@Column()
estatus: boolean
/*
@OneToOne(() => Qr, (qr) => qr.participanteEvento)
qr: Qr;
@ManyToOne(() => Participante, (participante) => participante.eventos)
@JoinColumn({ name: "id_participante" })
participante: Participante;
@ManyToOne(() => Evento, (evento) => evento.participantes)
@JoinColumn({ name: "id_evento" })
evento: Evento;
*/
@ManyToOne(() => Evento, (evento) => evento.participantes)
@JoinColumn({ name: "id_evento" })
evento: Evento;
}
@@ -0,0 +1,13 @@
import { Module } from '@nestjs/common';
import { ParticipanteEventoService } from './participante_evento.service';
import { ParticipanteEventoController } from './participante_evento.controller';
import { TypeOrmModule } from '@nestjs/typeorm';
import { ParticipanteEvento } from './participante_evento.entity';
import { Evento } from 'src/evento/evento.entity';
@Module({
imports: [TypeOrmModule.forFeature([ParticipanteEvento]), Evento],
controllers: [ParticipanteEventoController],
providers: [ParticipanteEventoService]
})
export class ParticipanteEventoModule {}
@@ -0,0 +1,77 @@
import { HttpException, HttpStatus, Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { ParticipanteEvento } from './participante_evento.entity';
import { Repository } from 'typeorm';
import { CreateParticipanteEventoDto } from './dto/create-participante_evento.dto';
import { UpdateParticipanteEventoDto } from './dto/update.participante_evento.dto';
@Injectable()
export class ParticipanteEventoService {
constructor(
@InjectRepository(ParticipanteEvento) private participanteEventoRepository: Repository<ParticipanteEvento>
) {}
async createParticipanteEvento(participanteEvento: CreateParticipanteEventoDto) {
const participante_eventoFound = await this.participanteEventoRepository.findOne({
where: {
id_participante: participanteEvento.id_participante,
id_evento: participanteEvento.id_evento
}
})
if (participante_eventoFound) {
return new HttpException('Participante already exists in this event', HttpStatus.CONFLICT)
}
return this.participanteEventoRepository.save(participanteEvento)
}
getParticipantesEvento() {
return this.participanteEventoRepository.find({
relations: ['evento']
})
}
async getParticipanteEvento(id_participante: number) {
const participante_eventoFound = await this.participanteEventoRepository.findOne({
where: {
id_participante
},
relations: ['evento']
})
if (!participante_eventoFound) {
return new HttpException('Participante not found', HttpStatus.NOT_FOUND);
}
return participante_eventoFound
}
async deleteParticipanteEvento(id_participante: number) {
const result = await this.participanteEventoRepository.delete({ id_participante })
if (result.affected === 0) {
return new HttpException('Participante not found', HttpStatus.NOT_FOUND);
}
return result
}
async updateParticipanteEvento(id_participante: number, id_evento: number, participante_evento: UpdateParticipanteEventoDto) {
const participante_eventoFound = await this.participanteEventoRepository.findOne({
where: {
id_participante,
id_evento
}
})
if (!participante_eventoFound) {
return new HttpException('Participante not found', HttpStatus.NOT_FOUND)
}
return this.participanteEventoRepository.save(participante_evento)
}
}
+6
View File
@@ -0,0 +1,6 @@
export class CreateQrDto {
id_participante_evento: number
fecha_creacion: Date
decha_vencimiento: Date
activo: boolean
}
+5
View File
@@ -0,0 +1,5 @@
export class UpdateQrDto {
fecha_creacion?: Date
fecha_vencimiento: Date
activo?: boolean
}
+36
View File
@@ -0,0 +1,36 @@
import { Body, Controller, Delete, Get, Param, ParseIntPipe, Patch, Post } from '@nestjs/common';
import { QrService } from './qr.service';
import { Qr } from './qr.entity';
import { CreateQrDto } from './dto/create-qr.dto';
import { UpdateQrDto } from './dto/update.qr.dto';
@Controller('qr')
export class QrController {
constructor(private qrService: QrService) {}
@Get()
getQrs(): Promise<Qr[]> {
return this.qrService.getQrs();
}
@Get(':id')
getQr(@Param('id', ParseIntPipe) id: number) {
return this.qrService.getQr(id);
}
@Post() //en el body ValidationPipe
createQr(@Body() newQr: CreateQrDto) {
return this.qrService.createQr(newQr)
}
@Delete(':id')
deleteQr(@Param('id', ParseIntPipe) id:number) {
return this.qrService.deleteQr(id);
}
@Patch(':id')
updateQr(@Param('id', ParseIntPipe) id: number, @Body() qr: UpdateQrDto) {
return this.qrService.updateQr(id, qr)
}
}
+25
View File
@@ -0,0 +1,25 @@
import { Column, Entity, PrimaryGeneratedColumn } from "typeorm";
@Entity()
export class Qr {
@PrimaryGeneratedColumn()
id_qr: number
/*
@OneToOne(() => ParticipanteEvento, (pe) => pe.qr)
@JoinColumn({ name: "id_participante_evento" })
participanteEvento: ParticipanteEvento;
*/
@Column({type: 'datetime', default: () => 'CURRENT_TIMESTAMP' })
fecha_creacion: Date
@Column({type: 'datetime', default: () => 'CURRENT_TIMESTAMP' })
fecha_vencimiento: Date
@Column()
activo: boolean
//Relacion con id_participante_evento
}
+12
View File
@@ -0,0 +1,12 @@
import { Module } from '@nestjs/common';
import { QrService } from './qr.service';
import { QrController } from './qr.controller';
import { TypeOrmModule } from '@nestjs/typeorm';
import { Qr } from './qr.entity';
@Module({
imports: [TypeOrmModule.forFeature([Qr])],
controllers: [QrController],
providers: [QrService]
})
export class QrModule {}
+73
View File
@@ -0,0 +1,73 @@
import { HttpException, HttpStatus, Injectable } from '@nestjs/common';
import { Qr } from './qr.entity';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { CreateQrDto } from './dto/create-qr.dto';
import { UpdateQrDto } from './dto/update.qr.dto';
@Injectable()
export class QrService {
constructor(
@InjectRepository(Qr) private qrRepository: Repository<Qr>
) {}
async createQr(qr: CreateQrDto) {
const qrFound = await this.qrRepository.findOne({
where: {
id_qr: qr.id_participante_evento
}
})
if (qrFound) {
return new HttpException('Qr already exists', HttpStatus.CONFLICT)
}
return this.qrRepository.save(qr)
}
getQrs() {
return this.qrRepository.find({})
}
async getQr(id_qr) {
const qrFound = await this.qrRepository.findOne({
where: {
id_qr
}
})
if (!qrFound) {
return new HttpException('User not found', HttpStatus.NOT_FOUND);
}
return qrFound
}
async deleteQr(id_qr: number) {
const result = await this.qrRepository.delete({ id_qr })
if (result.affected === 0) {
return new HttpException('User not found', HttpStatus.NOT_FOUND);
}
return result
}
async updateQr(id_qr: number, qr: UpdateQrDto) {
const qrFound = await this.qrRepository.findOne({
where: {
id_qr
}
})
if (!qrFound) {
return new HttpException('User not found', HttpStatus.NOT_FOUND)
}
const updateQr = Object.assign(qrFound, qr)
return this.qrRepository.save(updateQr)
}
}
@@ -0,0 +1,7 @@
export class CreateTipoUserDto {
tipo: string
nombre: string
apellido_p: string
apellido_m: string
correo?: string
}
@@ -0,0 +1,6 @@
export class UpdateTipoUserDto {
tipo?: string
nombre?: string
apellido_p?: string
apellido_m: string
}
+63
View File
@@ -0,0 +1,63 @@
import { Body, Controller, Delete, Get, Param, ParseIntPipe, Patch, Post } from '@nestjs/common';
import { TipoUserService } from './tipo_user.service';
import { TipoUser } from './tipo_user.entity';
import { CreateTipoUserDto } from './dto/create-tipo-user.dto';
import { UpdateTipoUserDto } from './dto/update.tipo_user.dto';
import { ApiTags, ApiOperation, ApiResponse, ApiParam, ApiBody } from '@nestjs/swagger';
@ApiTags('Tipo de Usuario') // Agrupa los endpoints en Swagger
@Controller('tipo-user')
export class TipoUserController {
constructor(private tipoUserService: TipoUserService) {}
@ApiOperation({ summary: 'Obtener todos los tipos de usuario' })
@ApiResponse({ status: 200, description: 'Lista de tipos de usuario obtenida correctamente.' })
@Get()
getTipoUsers(): Promise<TipoUser[]> {
return this.tipoUserService.getTipoUsers();
}
@Get(':id')
@ApiOperation({ summary: 'Obtener un tipo de usuario por ID' })
@ApiParam({ name: 'id', description: 'ID del tipo de usuario', example: 1 })
@ApiResponse({ status: 200, description: 'Tipo de usuario obtenido correctamente.' })
@ApiResponse({ status: 404, description: 'Tipo de usuario no encontrado.' })
getTipoUser(@Param('id', ParseIntPipe) id: number) {
return this.tipoUserService.getTipoUser(id);
}
@Post()
@ApiOperation({
summary: 'Crear un tipo de usuario',
description: 'Este endpoint permite registrar un nuevo tipo de usuario en el sistema.',
})
@ApiBody({
description: 'Datos del tipo de usuario',
schema: {
type: 'object',
properties: {
tipo: { type: 'string', example: 'Administrador' },
nombre: { type: 'string', example: 'Juan' },
apellido_p: { type: 'string', example: 'Pérez' },
apellido_m: { type: 'string', example: 'Gómez' },
},
},
})
@ApiResponse({ status: 201, description: 'Tipo de usuario creado correctamente.' })
@ApiResponse({ status: 400, description: 'Datos inválidos en la solicitud.' })
createTipoUser(@Body() newTipoUser: CreateTipoUserDto) {
return this.tipoUserService.createTipoUser(newTipoUser)
}
@Delete(':id')
deleteTipoUser(@Param('id', ParseIntPipe) id:number) {
return this.tipoUserService.deleteTipoUser(id)
}
@Patch()
updateTipoUser(@Param(':id', ParseIntPipe) id: number, @Body() tipoUser: UpdateTipoUserDto) {
return this.tipoUserService.updateTipoUser(id, tipoUser)
}
}
+28
View File
@@ -0,0 +1,28 @@
import { Administrador } from "src/administrador/administrador.entity";
import { Participante } from "src/participante/participante.entity";
import { Column, Entity, OneToMany, PrimaryGeneratedColumn } from "typeorm";
@Entity()
export class TipoUser {
@PrimaryGeneratedColumn()
id_tipo_user: number;
@Column()
tipo: string;
@Column()
nombre: string;
@Column({nullable: true})
apellido_p: string;
@Column({nullable: true})
apellido_m: string;
@OneToMany(() => Participante, participante => participante.tipo_user)
participante: Participante[]
@OneToMany(() => Administrador, administrador => administrador.tipoUser)
administrador: Administrador[]
}
+16
View File
@@ -0,0 +1,16 @@
import { Module } from '@nestjs/common';
import { TipoUserService } from './tipo_user.service';
import { TypeOrmModule } from '@nestjs/typeorm';
import { TipoUser } from './tipo_user.entity';
import { TipoUserController } from './tipo_user.controller';
import { Administrador } from 'src/administrador/administrador.entity';
import { Participante } from 'src/participante/participante.entity';
@Module({
imports: [TypeOrmModule.forFeature([TipoUser, Administrador, Participante])],
controllers: [TipoUserController],
providers: [TipoUserService],
exports: [TipoUserService]
})
export class TipoUserModule {}
+126
View File
@@ -0,0 +1,126 @@
import { BadRequestException, HttpException, HttpStatus, Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { TipoUser } from './tipo_user.entity';
import { Repository } from 'typeorm';
import { CreateTipoUserDto } from './dto/create-tipo-user.dto';
import { UpdateTipoUserDto } from './dto/update.tipo_user.dto';
import { Participante } from 'src/participante/participante.entity';
import { Administrador } from 'src/administrador/administrador.entity';
@Injectable()
export class TipoUserService {
constructor(
@InjectRepository(TipoUser) private tipoUserRepository: Repository<TipoUser>,
@InjectRepository(Participante) private participanteRepository: Repository<Participante>,
@InjectRepository(Administrador) private administradorRepository: Repository<Administrador>,
) {}
/*
//Funcion para registrar usuario
async registrarUsuario(dto: CreateTipoUserDto) {
// Crear el registro en tipo_user
const tipoUser = this.tipoUserRepository.create({
tipo: dto.tipo,
nombre: dto.nombre,
apellido_p: dto.apellido_p,
apellido_m: dto.apellido_m,
});
await this.tipoUserRepository.save(tipoUser);
// Si es participante, insertar en participante
if (dto.tipo === 'participante') {
if (!dto.correo) {
throw new BadRequestException('El correo es obligatorio para participantes');
}
const participante = this.participanteRepository.create({
correo: dto.correo,
tipo_user: tipoUser, // Relación con tipo_user
});
await this.participanteRepository.save(participante);
}
// Si es administrador, insertar en administrador
if (dto.tipo === 'administrador') {
const administrador = this.administradorRepository.create({
tipoUser: tipoUser, // Relación con tipo_user
});
await this.administradorRepository.save(administrador);
}
return { message: 'Usuario registrado correctamente' };
}
}
*/
async createTipoUser(tipoUser: CreateTipoUserDto) {
// falta hacer la validacion
const tipo_userFound = await this.tipoUserRepository.findOne({
where: {
nombre: tipoUser.nombre,
tipo: tipoUser.tipo,
//id_tipo_user:
}
})
if(tipo_userFound) {
return new HttpException('Tipo User already exict', HttpStatus.NOT_FOUND);
}
const tipo_user = this.tipoUserRepository.create(tipoUser)
return this.tipoUserRepository.save(tipo_user)
}
getTipoUsers() {
return this.tipoUserRepository.find({
relations: ['participante', 'administrador']
})
}
async getTipoUser(id: number) {
const tipo_userFound = await this.tipoUserRepository.findOne({
where: {
id_tipo_user: id
},
relations: ['participante', 'administrador']
});
if(!tipo_userFound) {
return new HttpException('User not found', HttpStatus.NOT_FOUND);
}
return tipo_userFound;
}
async deleteTipoUser(id_tipo_user: number) {
const result = await this.tipoUserRepository.delete({ id_tipo_user })
if(result.affected === 0) {
return new HttpException('User not found', HttpStatus.NOT_FOUND);
}
return result
}
async updateTipoUser(id_tipo_user: number, tipo_user: UpdateTipoUserDto) {
const tipo_userFound = await this.tipoUserRepository.findOne({
where: {
id_tipo_user
}
})
if(!tipo_userFound) {
return new HttpException('User not found', HttpStatus.NOT_FOUND)
}
const updateTipoUser = Object.assign(tipo_userFound, tipo_user)
return this.tipoUserRepository.save(updateTipoUser)
}
}