diff --git a/notas_santi.txt b/notas_santi.txt new file mode 100644 index 0000000..eca430e --- /dev/null +++ b/notas_santi.txt @@ -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" + } +} diff --git a/package-lock.json b/package-lock.json index d47efe7..8815789 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,13 +9,16 @@ "version": "0.0.1", "license": "UNLICENSED", "dependencies": { - "@nestjs/common": "^11.0.1", + "@nestjs/common": "^11.0.12", "@nestjs/config": "^4.0.2", "@nestjs/core": "^11.0.1", "@nestjs/mapped-types": "*", "@nestjs/platform-express": "^11.0.1", + "@nestjs/swagger": "^11.1.0", "@nestjs/typeorm": "^11.0.0", "class-validator": "^0.14.1", + "dotenv": "^16.4.7", + "mysql2": "^3.14.0", "reflect-metadata": "^0.2.2", "rxjs": "^7.8.1", "typeorm": "^0.3.21" @@ -44,7 +47,7 @@ "ts-loader": "^9.5.2", "ts-node": "^10.9.2", "tsconfig-paths": "^4.2.0", - "typescript": "^5.7.3", + "typescript": "^5.8.2", "typescript-eslint": "^8.20.0" } }, @@ -1906,6 +1909,12 @@ "node": ">=8" } }, + "node_modules/@microsoft/tsdoc": { + "version": "0.15.1", + "resolved": "https://registry.npmjs.org/@microsoft/tsdoc/-/tsdoc-0.15.1.tgz", + "integrity": "sha512-4aErSrCR/On/e5G2hDP0wjooqDdauzEbIq8hIkIe5pXV0rtWJZvdCEKL0ykZxex+IxIwBp0eGeV48hQN07dXtw==", + "license": "MIT" + }, "node_modules/@napi-rs/nice": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@napi-rs/nice/-/nice-1.0.1.tgz", @@ -2495,6 +2504,39 @@ "tslib": "^2.1.0" } }, + "node_modules/@nestjs/swagger": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/@nestjs/swagger/-/swagger-11.1.0.tgz", + "integrity": "sha512-+GQ+q1ASTBvGi0DYHukWi8NVVVLszedwLLqHdLRnJh8rjokt8YTDb7roImvT/YMmYgPvaWBv/4JYdZH4FueLPQ==", + "license": "MIT", + "dependencies": { + "@microsoft/tsdoc": "0.15.1", + "@nestjs/mapped-types": "2.1.0", + "js-yaml": "4.1.0", + "lodash": "4.17.21", + "path-to-regexp": "8.2.0", + "swagger-ui-dist": "5.20.1" + }, + "peerDependencies": { + "@fastify/static": "^8.0.0", + "@nestjs/common": "^11.0.1", + "@nestjs/core": "^11.0.1", + "class-transformer": "*", + "class-validator": "*", + "reflect-metadata": "^0.1.12 || ^0.2.0" + }, + "peerDependenciesMeta": { + "@fastify/static": { + "optional": true + }, + "class-transformer": { + "optional": true + }, + "class-validator": { + "optional": true + } + } + }, "node_modules/@nestjs/testing": { "version": "11.0.12", "resolved": "https://registry.npmjs.org/@nestjs/testing/-/testing-11.0.12.tgz", @@ -2613,6 +2655,13 @@ "url": "https://opencollective.com/unts" } }, + "node_modules/@scarf/scarf": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@scarf/scarf/-/scarf-1.4.0.tgz", + "integrity": "sha512-xxeapPiUXdZAE3che6f3xogoJPeZgig6omHEy1rIY5WVsB3H2BHNnZH+gHG6x91SCWyQCzWGsuL2Hh3ClO5/qQ==", + "hasInstallScript": true, + "license": "Apache-2.0" + }, "node_modules/@sec-ant/readable-stream": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/@sec-ant/readable-stream/-/readable-stream-0.4.1.tgz", @@ -4115,7 +4164,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true, "license": "Python-2.0" }, "node_modules/array-timsort": { @@ -4146,6 +4194,15 @@ "dev": true, "license": "MIT" }, + "node_modules/aws-ssl-profiles": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/aws-ssl-profiles/-/aws-ssl-profiles-1.1.2.tgz", + "integrity": "sha512-NZKeq9AfyQvEeNlN0zSYAaWrmBffJh3IELMZfRpJVWgrpEbtEpnjvzqBPf+mxoI287JohRDoa+/nsfqqiZmF6g==", + "license": "MIT", + "engines": { + "node": ">= 6.0.0" + } + }, "node_modules/b4a": { "version": "1.6.7", "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.6.7.tgz", @@ -5248,6 +5305,15 @@ "node": ">=0.4.0" } }, + "node_modules/denque": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz", + "integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==", + "license": "Apache-2.0", + "engines": { + "node": ">=0.10" + } + }, "node_modules/depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", @@ -6499,6 +6565,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/generate-function": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz", + "integrity": "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==", + "license": "MIT", + "dependencies": { + "is-property": "^1.0.2" + } + }, "node_modules/gensync": { "version": "1.0.0-beta.2", "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", @@ -7077,6 +7152,12 @@ "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==", "license": "MIT" }, + "node_modules/is-property": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", + "integrity": "sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g==", + "license": "MIT" + }, "node_modules/is-stream": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", @@ -7912,7 +7993,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, "license": "MIT", "dependencies": { "argparse": "^2.0.1" @@ -8125,6 +8205,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/long": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/long/-/long-5.3.1.tgz", + "integrity": "sha512-ka87Jz3gcx/I7Hal94xaN2tZEOPoUOEVftkQqZx2EeQRN7LGdfLlI3FvZ+7WDplm+vK2Urx9ULrvSowtdCieng==", + "license": "Apache-2.0" + }, "node_modules/lowercase-keys": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-3.0.0.tgz", @@ -8148,6 +8234,21 @@ "yallist": "^3.0.2" } }, + "node_modules/lru.min": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/lru.min/-/lru.min-1.1.2.tgz", + "integrity": "sha512-Nv9KddBcQSlQopmBHXSsZVY5xsdlZkdH/Iey0BlcBYggMd4two7cZnKOK9vmy3nY0O5RGH99z1PCeTpPqszUYg==", + "license": "MIT", + "engines": { + "bun": ">=1.0.0", + "deno": ">=1.30.0", + "node": ">=8.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wellwelwel" + } + }, "node_modules/magic-string": { "version": "0.30.17", "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz", @@ -8464,6 +8565,59 @@ "node": "^18.17.0 || >=20.5.0" } }, + "node_modules/mysql2": { + "version": "3.14.0", + "resolved": "https://registry.npmjs.org/mysql2/-/mysql2-3.14.0.tgz", + "integrity": "sha512-8eMhmG6gt/hRkU1G+8KlGOdQi2w+CgtNoD1ksXZq9gQfkfDsX4LHaBwTe1SY0Imx//t2iZA03DFnyYKPinxSRw==", + "license": "MIT", + "dependencies": { + "aws-ssl-profiles": "^1.1.1", + "denque": "^2.1.0", + "generate-function": "^2.3.1", + "iconv-lite": "^0.6.3", + "long": "^5.2.1", + "lru.min": "^1.0.0", + "named-placeholders": "^1.1.3", + "seq-queue": "^0.0.5", + "sqlstring": "^2.3.2" + }, + "engines": { + "node": ">= 8.0" + } + }, + "node_modules/mysql2/node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/named-placeholders": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/named-placeholders/-/named-placeholders-1.1.3.tgz", + "integrity": "sha512-eLoBxg6wE/rZkJPhU/xRX1WTpkFEwDJEN96oxFrTsqBdbT5ec295Q+CoHrL9IT0DipqKhmGcaZmwOt8OON5x1w==", + "license": "MIT", + "dependencies": { + "lru-cache": "^7.14.1" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/named-placeholders/node_modules/lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, "node_modules/natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", @@ -9637,6 +9791,11 @@ "node": ">= 0.6" } }, + "node_modules/seq-queue": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/seq-queue/-/seq-queue-0.0.5.tgz", + "integrity": "sha512-hr3Wtp/GZIc/6DAGPDcV4/9WoZhjrkXsi5B/07QgX8tsdc6ilr7BFM6PM6rbdAX1kFSDYeZGLipIZZKyQP0O5Q==" + }, "node_modules/serialize-javascript": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", @@ -9883,6 +10042,15 @@ "node": ">=14" } }, + "node_modules/sqlstring": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.3.tgz", + "integrity": "sha512-qC9iz2FlN7DQl3+wjwn3802RTyjCx7sDvfQEXchwa6CWOx07/WVfh91gBmQ9fahw8snwGEWU3xGzOt4tFyHLxg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/stack-utils": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", @@ -10220,6 +10388,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/swagger-ui-dist": { + "version": "5.20.1", + "resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-5.20.1.tgz", + "integrity": "sha512-qBPCis2w8nP4US7SvUxdJD3OwKcqiWeZmjN2VWhq2v+ESZEXOP/7n4DeiOiiZcGYTKMHAHUUrroHaTsjUWTEGw==", + "license": "Apache-2.0", + "dependencies": { + "@scarf/scarf": "=1.4.0" + } + }, "node_modules/symbol-observable": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-4.0.0.tgz", diff --git a/package.json b/package.json index b3ae839..f18668e 100644 --- a/package.json +++ b/package.json @@ -20,13 +20,16 @@ "test:e2e": "jest --config ./test/jest-e2e.json" }, "dependencies": { - "@nestjs/common": "^11.0.1", + "@nestjs/common": "^11.0.12", "@nestjs/config": "^4.0.2", "@nestjs/core": "^11.0.1", "@nestjs/mapped-types": "*", "@nestjs/platform-express": "^11.0.1", + "@nestjs/swagger": "^11.1.0", "@nestjs/typeorm": "^11.0.0", "class-validator": "^0.14.1", + "dotenv": "^16.4.7", + "mysql2": "^3.14.0", "reflect-metadata": "^0.2.2", "rxjs": "^7.8.1", "typeorm": "^0.3.21" @@ -55,7 +58,7 @@ "ts-loader": "^9.5.2", "ts-node": "^10.9.2", "tsconfig-paths": "^4.2.0", - "typescript": "^5.7.3", + "typescript": "^5.8.2", "typescript-eslint": "^8.20.0" }, "jest": { diff --git a/src/administrador/administrador.controller.ts b/src/administrador/administrador.controller.ts new file mode 100644 index 0000000..f0b8cb0 --- /dev/null +++ b/src/administrador/administrador.controller.ts @@ -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 { + 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) + } + +} diff --git a/src/administrador/administrador.entity.ts b/src/administrador/administrador.entity.ts new file mode 100644 index 0000000..483ba96 --- /dev/null +++ b/src/administrador/administrador.entity.ts @@ -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[]; + */ +} \ No newline at end of file diff --git a/src/administrador/administrador.module.ts b/src/administrador/administrador.module.ts new file mode 100644 index 0000000..17ed104 --- /dev/null +++ b/src/administrador/administrador.module.ts @@ -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 {} diff --git a/src/administrador/administrador.service.ts b/src/administrador/administrador.service.ts new file mode 100644 index 0000000..2dce554 --- /dev/null +++ b/src/administrador/administrador.service.ts @@ -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 + ) {} + + 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) + } + +} diff --git a/src/administrador/dto/create-administrador.dto.ts b/src/administrador/dto/create-administrador.dto.ts new file mode 100644 index 0000000..fedb2b3 --- /dev/null +++ b/src/administrador/dto/create-administrador.dto.ts @@ -0,0 +1,3 @@ +export class CreateAdministradorDto { + id_tipo_user: number +} \ No newline at end of file diff --git a/src/administrador/dto/update.administrador.dto.ts b/src/administrador/dto/update.administrador.dto.ts new file mode 100644 index 0000000..f1355f2 --- /dev/null +++ b/src/administrador/dto/update.administrador.dto.ts @@ -0,0 +1,3 @@ +export class UpdateAdministradorDto { + id_tipo_user?: number +} \ No newline at end of file diff --git a/src/app.module.ts b/src/app.module.ts index 3d16193..1bcc365 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -1,3 +1,4 @@ +//import { Module } from '@nestjs/common; import { Module } from '@nestjs/common'; import { AppController } from './app.controller'; import { AppService } from './app.service'; @@ -15,14 +16,22 @@ import { CuestionarioRespondidoModule } from './cuestionario_respondido/cuestion import { RespuestaParticipanteAbiertaModule } from './respuesta_participante_abierta/respuesta_participante_abierta.module'; import { TypeOrmModule } from '@nestjs/typeorm'; import { ConfigModule } from '@nestjs/config'; +import { EventoModule } from './evento/evento.module'; +import { TipoUserModule } from './tipo_user/tipo_user.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: [ ConfigModule.forRoot(), TypeOrmModule.forRoot({ + /* type: 'mysql', - host: process.env.db_host, + host: process.env.db_host, //process.env.db_host username: process.env.db_username, database: process.env.db_database, password: process.env.db_password, @@ -31,7 +40,19 @@ import { ConfigModule } from '@nestjs/config'; dropSchema: true, // elimina la base de datos // logging: true, // Habilita los logs para depuración autoLoadEntities: true, // Carga automáticamente las entidades - + */ + //esta es mi base de datos local + type: 'mysql', + host: 'localhost', + port: 3306, //3306 + username: 'root', + password: 'admin', //admin + database: 'cidwa', //nestdb + entities: [__dirname + '/**/*.entity{.ts,.js}'], + synchronize: true, + //extra + retryAttempts: 10, // Intentos para reconectar + retryDelay: 3000, // Tiempo entre reintentos }), CuestionarioModule, TipoCuestionarioModule, @@ -43,7 +64,15 @@ import { ConfigModule } from '@nestjs/config'; OpcionModule, PreguntaOpcionModule, RespuestaParticipanteCerradaModule, CuestionarioRespondidoModule, - RespuestaParticipanteAbiertaModule], + RespuestaParticipanteAbiertaModule, + EventoModule, + TipoUserModule, + ParticipanteModule, + QrModule, + AdministradorModule, + AsistenciaModule, + ParticipanteEventoModule, + ], controllers: [AppController], providers: [AppService], diff --git a/src/asistencia/asistencia.controller.ts b/src/asistencia/asistencia.controller.ts new file mode 100644 index 0000000..1107ab8 --- /dev/null +++ b/src/asistencia/asistencia.controller.ts @@ -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 { + 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) + } + +} diff --git a/src/asistencia/asistencia.entity.ts b/src/asistencia/asistencia.entity.ts new file mode 100644 index 0000000..83c5dc5 --- /dev/null +++ b/src/asistencia/asistencia.entity.ts @@ -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; + */ +} \ No newline at end of file diff --git a/src/asistencia/asistencia.module.ts b/src/asistencia/asistencia.module.ts new file mode 100644 index 0000000..f16c339 --- /dev/null +++ b/src/asistencia/asistencia.module.ts @@ -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 {} diff --git a/src/asistencia/asistencia.service.ts b/src/asistencia/asistencia.service.ts new file mode 100644 index 0000000..1732a79 --- /dev/null +++ b/src/asistencia/asistencia.service.ts @@ -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 + ) {} + + 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) + } + + +} diff --git a/src/asistencia/dto/create-asistencia.dto.ts b/src/asistencia/dto/create-asistencia.dto.ts new file mode 100644 index 0000000..e3da47e --- /dev/null +++ b/src/asistencia/dto/create-asistencia.dto.ts @@ -0,0 +1,5 @@ +export class CreateAsistenciaDto { + fecha_asistencia: Date + metodo: boolean + estdao: boolean +} \ No newline at end of file diff --git a/src/asistencia/dto/update.asistencia.dto.ts b/src/asistencia/dto/update.asistencia.dto.ts new file mode 100644 index 0000000..23588e4 --- /dev/null +++ b/src/asistencia/dto/update.asistencia.dto.ts @@ -0,0 +1,5 @@ +export class UpdateAsistenciaDto { + fecha_asistencia?: Date + metodo?: boolean + estado?: boolean +} \ No newline at end of file diff --git a/src/cuestionario_respondido/entities/cuestionario_respondido.entity.ts b/src/cuestionario_respondido/entities/cuestionario_respondido.entity.ts index b1a3e5f..77e21e7 100644 --- a/src/cuestionario_respondido/entities/cuestionario_respondido.entity.ts +++ b/src/cuestionario_respondido/entities/cuestionario_respondido.entity.ts @@ -3,6 +3,7 @@ import { Entity, PrimaryGeneratedColumn, Column, ManyToOne, OneToMany, JoinColum import { Cuestionario } from 'src/cuestionario/entities/cuestionario.entity'; import { RespuestaParticipanteCerrada } from 'src/respuesta_participante_cerrada/entities/respuesta_participante_cerrada.entity'; import { RespuestaParticipanteAbierta } from 'src/respuesta_participante_abierta/entities/respuesta_participante_abierta.entity'; +import { Participante } from 'src/participante/participante.entity'; @Entity('cuestionario_respondido') export class CuestionarioRespondido { diff --git a/src/docs/docs.module.ts b/src/docs/docs.module.ts new file mode 100644 index 0000000..90d1820 --- /dev/null +++ b/src/docs/docs.module.ts @@ -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); + } +} diff --git a/src/docs/swagger.config.ts b/src/docs/swagger.config.ts new file mode 100644 index 0000000..e0e99a1 --- /dev/null +++ b/src/docs/swagger.config.ts @@ -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(); diff --git a/src/evento/dto/create-evento.dto.ts b/src/evento/dto/create-evento.dto.ts new file mode 100644 index 0000000..5fa9fd6 --- /dev/null +++ b/src/evento/dto/create-evento.dto.ts @@ -0,0 +1,11 @@ +export class CreateEventoDto { + tipo_evento: string; + + nombre_evento: string; + + fecha_inicio: Date; + + fecha_fin: Date; + + //agregar el id del administrador +} \ No newline at end of file diff --git a/src/evento/dto/update.evento.dto.ts b/src/evento/dto/update.evento.dto.ts new file mode 100644 index 0000000..f85579b --- /dev/null +++ b/src/evento/dto/update.evento.dto.ts @@ -0,0 +1,6 @@ +export class UpdateEventoDto { + tipo_evento?: string + nombre_evento: string + fecha_inicio?: Date + fecha_fin?: Date +} \ No newline at end of file diff --git a/src/evento/evento.controller.ts b/src/evento/evento.controller.ts new file mode 100644 index 0000000..0586840 --- /dev/null +++ b/src/evento/evento.controller.ts @@ -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 { + 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) + } + + +} diff --git a/src/evento/evento.entity.ts b/src/evento/evento.entity.ts new file mode 100644 index 0000000..046a042 --- /dev/null +++ b/src/evento/evento.entity.ts @@ -0,0 +1,41 @@ +import { Participante } from "src/participante/participante.entity"; +import { ParticipanteEvento } from "src/participante_evento/participante_evento.entity"; +import { Column, Entity, ManyToMany, 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(() => Asistencia, (asistencia) => asistencia.evento) + asistencias: Asistencia[]; + */ + + + + @OneToMany(() => ParticipanteEvento, participanteEvento => participanteEvento.evento) + participanteEventos: ParticipanteEvento[]; + +} \ No newline at end of file diff --git a/src/evento/evento.module.ts b/src/evento/evento.module.ts new file mode 100644 index 0000000..58e904d --- /dev/null +++ b/src/evento/evento.module.ts @@ -0,0 +1,13 @@ +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], + exports: [EventoService] +}) +export class EventoModule {} diff --git a/src/evento/evento.service.ts b/src/evento/evento.service.ts new file mode 100644 index 0000000..eaf5d9f --- /dev/null +++ b/src/evento/evento.service.ts @@ -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, + ) {} + + 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) + } +} diff --git a/src/main.ts b/src/main.ts index f76bc8d..e1c5710 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,8 +1,16 @@ import { NestFactory } from '@nestjs/core'; import { AppModule } from './app.module'; +import 'dotenv/config'; +import { DocsModule } from './docs/docs.module'; async function bootstrap() { const app = await NestFactory.create(AppModule); - await app.listen(process.env.PORT ?? 3000); + //await app.listen(process.env.PORT ?? 3000); + + DocsModule.setupSwagger(app); + + await app.listen(3000); + console.log('API en ejecución en http://localhost:3000'); + console.log('Swagger disponible en http://localhost:3000/api-docs'); } bootstrap(); diff --git a/src/opcion/dto/create-opcion.dto.ts b/src/opcion/dto/create-opcion.dto.ts index 69957f1..428eff5 100644 --- a/src/opcion/dto/create-opcion.dto.ts +++ b/src/opcion/dto/create-opcion.dto.ts @@ -1,8 +1,6 @@ import { IsString, MaxLength } from "class-validator"; export class CreateOpcionDto { - - @IsString() @MaxLength(50) opcion: string; diff --git a/src/opcion/opcion.module.ts b/src/opcion/opcion.module.ts index b638a8a..d5cb46a 100644 --- a/src/opcion/opcion.module.ts +++ b/src/opcion/opcion.module.ts @@ -1,9 +1,13 @@ import { Module } from '@nestjs/common'; import { OpcionService } from './opcion.service'; import { OpcionController } from './opcion.controller'; +import { TypeOrmModule } from '@nestjs/typeorm'; +import { Opcion } from './entities/opcion.entity'; @Module({ + imports: [TypeOrmModule.forFeature([Opcion])], // Importa el repositorio de Opcion controllers: [OpcionController], providers: [OpcionService], + exports: [OpcionService] }) export class OpcionModule {} diff --git a/src/opcion/opcion.service.ts b/src/opcion/opcion.service.ts index 9c44854..93e9267 100644 --- a/src/opcion/opcion.service.ts +++ b/src/opcion/opcion.service.ts @@ -12,12 +12,16 @@ export class OpcionService { private repository: Repository, ){} + create(createOpcionDto: CreateOpcionDto) { + return this.repository.save(createOpcionDto); + } + - + /* create():Promise { return this.repository.save(this.repository.create()); } - + */ findAll() { return `This action returns all opcion`; } diff --git a/src/participante/dto/create-participante.dto.ts b/src/participante/dto/create-participante.dto.ts new file mode 100644 index 0000000..3aae94f --- /dev/null +++ b/src/participante/dto/create-participante.dto.ts @@ -0,0 +1,7 @@ +import { IsEmail } from "class-validator"; + +export class CreateParticipanteDto { + @IsEmail() + correo: string + id_tipo_user: number +} \ No newline at end of file diff --git a/src/participante/dto/update.participante.dto.ts b/src/participante/dto/update.participante.dto.ts new file mode 100644 index 0000000..9cc03ba --- /dev/null +++ b/src/participante/dto/update.participante.dto.ts @@ -0,0 +1,3 @@ +export class UpdateParticipanteDto { + correo: string +} \ No newline at end of file diff --git a/src/participante/participante.controller.ts b/src/participante/participante.controller.ts new file mode 100644 index 0000000..f688879 --- /dev/null +++ b/src/participante/participante.controller.ts @@ -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 { + 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); + } + + + +} diff --git a/src/participante/participante.entity.ts b/src/participante/participante.entity.ts new file mode 100644 index 0000000..7bf4ae1 --- /dev/null +++ b/src/participante/participante.entity.ts @@ -0,0 +1,49 @@ +import { CuestionarioRespondido } from "src/cuestionario_respondido/entities/cuestionario_respondido.entity"; +import { Evento } from "src/evento/evento.entity"; +import { ParticipanteEvento } from "src/participante_evento/participante_evento.entity"; +import { TipoUser } from "src/tipo_user/tipo_user.entity"; +import { Column, Entity, JoinColumn, JoinTable, ManyToMany, 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; + + @ManyToMany(() => Evento, evento => evento.participantes) + @JoinTable({ + name: "participante_evento", + joinColumn: { name: "id_participante", referencedColumnName: "id_participante" }, + inverseJoinColumn: { name: "id_evento", referencedColumnName: "id_evento" } + }) + eventos: Evento[]; + + @OneToMany(() => Asistencia, (asistencia) => asistencia.evento) + asistencias: Asistencia[]; + */ + + + + @OneToMany(() => CuestionarioRespondido, cuestionario => cuestionario.id_participante) + cuestionariosRespondidos: CuestionarioRespondido[]; + + @OneToMany(() => ParticipanteEvento, participanteEvento => participanteEvento.participante) + participanteEventos: ParticipanteEvento[]; + + +} \ No newline at end of file diff --git a/src/participante/participante.module.ts b/src/participante/participante.module.ts new file mode 100644 index 0000000..912cd0c --- /dev/null +++ b/src/participante/participante.module.ts @@ -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 {} diff --git a/src/participante/participante.service.ts b/src/participante/participante.service.ts new file mode 100644 index 0000000..746cabc --- /dev/null +++ b/src/participante/participante.service.ts @@ -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 + ) {} + + 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', 'participanteEventos'] + }) + } + + async getParticipante(id_participante: number) { + const participanteFound = await this.participanteRepository.findOne({ + where: { + id_participante + }, + relations: ['tipo_user', 'participanteEventos'] + }) + + 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) + } + +} diff --git a/src/participante_evento/dto/create-participante_evento.dto.ts b/src/participante_evento/dto/create-participante_evento.dto.ts new file mode 100644 index 0000000..44b8994 --- /dev/null +++ b/src/participante_evento/dto/create-participante_evento.dto.ts @@ -0,0 +1,5 @@ +export class CreateParticipanteEventoDto { + id_participante: number + + id_evento: number +} \ No newline at end of file diff --git a/src/participante_evento/dto/update.participante_evento.dto.ts b/src/participante_evento/dto/update.participante_evento.dto.ts new file mode 100644 index 0000000..020e021 --- /dev/null +++ b/src/participante_evento/dto/update.participante_evento.dto.ts @@ -0,0 +1,6 @@ +export class UpdateParticipanteEventoDto { + id_participante?: number + id_evento?: number + fecha_inscripcion?: Date + estatus?: boolean +} \ No newline at end of file diff --git a/src/participante_evento/participante_evento.controller.ts b/src/participante_evento/participante_evento.controller.ts new file mode 100644 index 0000000..9d128e8 --- /dev/null +++ b/src/participante_evento/participante_evento.controller.ts @@ -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 { + 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) + } +} diff --git a/src/participante_evento/participante_evento.entity.ts b/src/participante_evento/participante_evento.entity.ts new file mode 100644 index 0000000..1451525 --- /dev/null +++ b/src/participante_evento/participante_evento.entity.ts @@ -0,0 +1,38 @@ +import { Evento } from "src/evento/evento.entity"; +import { Participante } from "src/participante/participante.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; + + @OneToMany(() => ParticipanteEvento, (pe) => pe.evento) + participantes: ParticipanteEvento[]; + + @ManyToOne(() => Evento, (evento) => evento.participantes) + @JoinColumn({ name: "id_evento" }) + evento: Evento; + */ + + @ManyToOne(() => Participante, participante => participante.participanteEventos) + @JoinColumn({ name: "id_participante" }) + participante: Participante; + + @ManyToOne(() => Evento, evento => evento.participanteEventos) + @JoinColumn({ name: "id_evento" }) + evento: Evento; + +} \ No newline at end of file diff --git a/src/participante_evento/participante_evento.module.ts b/src/participante_evento/participante_evento.module.ts new file mode 100644 index 0000000..aa7ba57 --- /dev/null +++ b/src/participante_evento/participante_evento.module.ts @@ -0,0 +1,15 @@ +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'; +import { Participante } from 'src/participante/participante.entity'; + +@Module({ + imports: [TypeOrmModule.forFeature([ParticipanteEvento, Evento, Participante])], + controllers: [ParticipanteEventoController], + providers: [ParticipanteEventoService], + exports: [ParticipanteEventoService], +}) +export class ParticipanteEventoModule {} diff --git a/src/participante_evento/participante_evento.service.ts b/src/participante_evento/participante_evento.service.ts new file mode 100644 index 0000000..38416a1 --- /dev/null +++ b/src/participante_evento/participante_evento.service.ts @@ -0,0 +1,81 @@ +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'; +import { Evento } from 'src/evento/evento.entity'; +import { Participante } from 'src/participante/participante.entity'; + +@Injectable() +export class ParticipanteEventoService { + + constructor( + @InjectRepository(ParticipanteEvento) private participanteEventoRepository: Repository, + @InjectRepository(Evento) private eventoRepository: Repository, + @InjectRepository(Participante) private participanteRepository: Repository + ) {} + + 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', 'participante'] + }) + } + + async getParticipanteEvento(id_participante: number) { + const participante_eventoFound = await this.participanteEventoRepository.findOne({ + where: { + id_participante + }, + relations: ['evento', 'participante'] + }) + + 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) + } + +} diff --git a/src/pregunta_opcion/entities/pregunta_opcion.entity.ts b/src/pregunta_opcion/entities/pregunta_opcion.entity.ts index 8cbd89c..7e76438 100644 --- a/src/pregunta_opcion/entities/pregunta_opcion.entity.ts +++ b/src/pregunta_opcion/entities/pregunta_opcion.entity.ts @@ -13,11 +13,11 @@ export class PreguntaOpcion { posicion: number; @ManyToOne(() => Pregunta, pregunta => pregunta.id_pregunta) - @Column() + //@Column() id_pregunta: Pregunta; @ManyToOne(() => Opcion, opcion => opcion.id_opcion) - @Column() + //@Column() id_opcion: Opcion; @OneToMany(()=> RespuestaParticipanteCerrada, respuestaParticipanteCerrada=>respuestaParticipanteCerrada.id_pregunta_opcion) diff --git a/src/qr/dto/create-qr.dto.ts b/src/qr/dto/create-qr.dto.ts new file mode 100644 index 0000000..b2fac5a --- /dev/null +++ b/src/qr/dto/create-qr.dto.ts @@ -0,0 +1,6 @@ +export class CreateQrDto { + id_participante_evento: number + fecha_creacion: Date + decha_vencimiento: Date + activo: boolean +} \ No newline at end of file diff --git a/src/qr/dto/update.qr.dto.ts b/src/qr/dto/update.qr.dto.ts new file mode 100644 index 0000000..6f59cf1 --- /dev/null +++ b/src/qr/dto/update.qr.dto.ts @@ -0,0 +1,5 @@ +export class UpdateQrDto { + fecha_creacion?: Date + fecha_vencimiento: Date + activo?: boolean +} \ No newline at end of file diff --git a/src/qr/qr.controller.ts b/src/qr/qr.controller.ts new file mode 100644 index 0000000..e09a48e --- /dev/null +++ b/src/qr/qr.controller.ts @@ -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 { + 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) + } +} diff --git a/src/qr/qr.entity.ts b/src/qr/qr.entity.ts new file mode 100644 index 0000000..9d6b3ac --- /dev/null +++ b/src/qr/qr.entity.ts @@ -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 + +} \ No newline at end of file diff --git a/src/qr/qr.module.ts b/src/qr/qr.module.ts new file mode 100644 index 0000000..1a6040e --- /dev/null +++ b/src/qr/qr.module.ts @@ -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 {} diff --git a/src/qr/qr.service.ts b/src/qr/qr.service.ts new file mode 100644 index 0000000..65af8d2 --- /dev/null +++ b/src/qr/qr.service.ts @@ -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 + ) {} + + 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) + } + + +} diff --git a/src/tipo_pregunta/tipo_pregunta.controller.ts b/src/tipo_pregunta/tipo_pregunta.controller.ts index e69de29..cc69f18 100644 --- a/src/tipo_pregunta/tipo_pregunta.controller.ts +++ b/src/tipo_pregunta/tipo_pregunta.controller.ts @@ -0,0 +1,6 @@ +import { Controller } from '@nestjs/common'; + +@Controller('tipo_pregunta') +export class TipoPreguntaController { + // Métodos del controlador +} diff --git a/src/tipo_pregunta/tipo_pregunta.service.ts b/src/tipo_pregunta/tipo_pregunta.service.ts index e69de29..197028b 100644 --- a/src/tipo_pregunta/tipo_pregunta.service.ts +++ b/src/tipo_pregunta/tipo_pregunta.service.ts @@ -0,0 +1,6 @@ +import { Injectable } from '@nestjs/common'; + +@Injectable() +export class TipoPreguntaService { + // Métodos del servicio +} diff --git a/src/tipo_user/dto/create-tipo-user.dto.ts b/src/tipo_user/dto/create-tipo-user.dto.ts new file mode 100644 index 0000000..4ab9314 --- /dev/null +++ b/src/tipo_user/dto/create-tipo-user.dto.ts @@ -0,0 +1,7 @@ +export class CreateTipoUserDto { + tipo: string + nombre: string + apellido_p: string + apellido_m: string + correo?: string +} \ No newline at end of file diff --git a/src/tipo_user/dto/update.tipo_user.dto.ts b/src/tipo_user/dto/update.tipo_user.dto.ts new file mode 100644 index 0000000..26dbfac --- /dev/null +++ b/src/tipo_user/dto/update.tipo_user.dto.ts @@ -0,0 +1,6 @@ +export class UpdateTipoUserDto { + tipo?: string + nombre?: string + apellido_p?: string + apellido_m: string +} \ No newline at end of file diff --git a/src/tipo_user/tipo_user.controller.ts b/src/tipo_user/tipo_user.controller.ts new file mode 100644 index 0000000..abed59a --- /dev/null +++ b/src/tipo_user/tipo_user.controller.ts @@ -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 { + 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) + } +} diff --git a/src/tipo_user/tipo_user.entity.ts b/src/tipo_user/tipo_user.entity.ts new file mode 100644 index 0000000..a20976e --- /dev/null +++ b/src/tipo_user/tipo_user.entity.ts @@ -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[] + +} \ No newline at end of file diff --git a/src/tipo_user/tipo_user.module.ts b/src/tipo_user/tipo_user.module.ts new file mode 100644 index 0000000..2caf76b --- /dev/null +++ b/src/tipo_user/tipo_user.module.ts @@ -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 {} diff --git a/src/tipo_user/tipo_user.service.ts b/src/tipo_user/tipo_user.service.ts new file mode 100644 index 0000000..f86d4a4 --- /dev/null +++ b/src/tipo_user/tipo_user.service.ts @@ -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, + @InjectRepository(Participante) private participanteRepository: Repository, + @InjectRepository(Administrador) private administradorRepository: Repository, + ) {} + + /* + //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) + } + +}