Compare commits
127 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 1abf4d4e9c | |||
| c73121f7df | |||
| 1a0af95c4e | |||
| 3ef076111e | |||
| 313bc7e632 | |||
| 29b0f2b3e5 | |||
| a387f11302 | |||
| e336f0bb86 | |||
| 017e6836e9 | |||
| 1155735d9d | |||
| e5f98c9596 | |||
| 24717cf931 | |||
| 02dd974fd6 | |||
| b6e7525dc2 | |||
| bc975bc295 | |||
| cb82dd3354 | |||
| a18fbe441d | |||
| c42c87e080 | |||
| 3bc245e1f7 | |||
| 5c5e7b3f0f | |||
| f50ce6d5f9 | |||
| 7933605cb1 | |||
| 963ec5a765 | |||
| 308f910bee | |||
| 29fdbee734 | |||
| ea14bfc96c | |||
| 9c677fa479 | |||
| 77f685e8d3 | |||
| 757fa541d8 | |||
| 0ee2f86c75 | |||
| 9d8c59d5ca | |||
| 592acee975 | |||
| c33817ace3 | |||
| bcb14ddeba | |||
| 0cf0c54879 | |||
| eb787c21e6 | |||
| 141afc824a | |||
| 617f4fe5bb | |||
| ad7fd3b513 | |||
| 71a24ca189 | |||
| ed5b64afb8 | |||
| c0178301ae | |||
| f70aa0f92e | |||
| 8762b51240 | |||
| c9cd073101 | |||
| 688e13b30c | |||
| 086af154cf | |||
| 400bffa254 | |||
| 61c164225c | |||
| 151d2e8718 | |||
| 62b71060be | |||
| 43abc72a38 | |||
| 04ad4923a5 | |||
| c40c82e7ba | |||
| 050c2b225c | |||
| ccd3781152 | |||
| 6a5d39d122 | |||
| 53c53d62a0 | |||
| 53ba7d45ff | |||
| 0ede1e8372 | |||
| 197b18910d | |||
| cafbce392d | |||
| a6efe25aa3 | |||
| 7b6b29b75f | |||
| 672f3579ac | |||
| 786f56442c | |||
| 90d791347e | |||
| 0aa5180154 | |||
| d6f5f645b8 | |||
| 115265381b | |||
| a851d31d3b | |||
| 29e4b4a7ad | |||
| cadb15a9cf | |||
| 83bbcee4ad | |||
| 8fac3a823a | |||
| b7d22cc07e | |||
| bba0aa12cc | |||
| ff6096f603 | |||
| 53b7d23007 | |||
| 8f68aadd8a | |||
| 9386fbc88d | |||
| 7686e26324 | |||
| 8f575aa662 | |||
| 19303178aa | |||
| 7d3a8ee5ed | |||
| 3aaf9ba0ed | |||
| af28549a04 | |||
| 50487e4859 | |||
| 6c22cfeeba | |||
| bf2367b366 | |||
| 0cb91d8b9e | |||
| 2ed657caf2 | |||
| 016297760f | |||
| 5f7ba5ff69 | |||
| bc4146a07d | |||
| 5567a26ed6 | |||
| 7a260169cc | |||
| 3e67102878 | |||
| 1c40eca428 | |||
| f62a868b97 | |||
| 65e0773337 | |||
| 671f989976 | |||
| 71e5ca35f9 | |||
| 6c0e263bf4 | |||
| aff3a44c09 | |||
| 083cefe84a | |||
| 340c0d59fd | |||
| 1b80de961b | |||
| 995a3a4e5e | |||
| a9b9b39285 | |||
| f25b60eccf | |||
| 0e6d6be3bb | |||
| 324ab9d35a | |||
| a6ee9decec | |||
| 75f55ba918 | |||
| e5a455bbb1 | |||
| 7b8514468f | |||
| 9d9df020db | |||
| 4770e95420 | |||
| c9c0a531f2 | |||
| cea20f387f | |||
| 373b99a57a | |||
| 6a871d8fa1 | |||
| 09e12161bd | |||
| b771ca2e57 | |||
| 4427804865 | |||
| f06decdc43 |
+7
-1
@@ -2,7 +2,8 @@
|
||||
/dist
|
||||
/node_modules
|
||||
/build
|
||||
|
||||
/server/uploads
|
||||
/server
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
@@ -12,6 +13,8 @@ yarn-debug.log*
|
||||
yarn-error.log*
|
||||
lerna-debug.log*
|
||||
|
||||
/initdb/init.sql
|
||||
/initdb2
|
||||
# OS
|
||||
.DS_Store
|
||||
|
||||
@@ -19,6 +22,9 @@ lerna-debug.log*
|
||||
/coverage
|
||||
/.nyc_output
|
||||
|
||||
# Ignorar credenciales sensibles
|
||||
cred.json
|
||||
|
||||
# IDEs and editors
|
||||
/.idea
|
||||
.project
|
||||
|
||||
+11
-26
@@ -1,33 +1,18 @@
|
||||
version: '3.8'
|
||||
|
||||
services:
|
||||
mysql:
|
||||
database:
|
||||
image: mariadb:latest
|
||||
container_name: Iris_db
|
||||
restart: always
|
||||
environment:
|
||||
MYSQL_ROOT_PASSWORD: root
|
||||
MYSQL_DATABASE: Iris
|
||||
MYSQL_USER: user_crud
|
||||
MYSQL_PASSWORD: root
|
||||
MARIADB_ROOT_PASSWORD: root
|
||||
MARIADB_DATABASE: Iris_testDB
|
||||
MARIADB_USER: root
|
||||
MARIADB_PASSWORD: root
|
||||
ports:
|
||||
- '3306:3306'
|
||||
volumes:
|
||||
- ./mysql:/var/lib/mysql
|
||||
ports:
|
||||
- "3307:3306"
|
||||
- mariadb_data:/var/lib/mysql
|
||||
- ./initdb2:/docker-entrypoint-initdb.dP
|
||||
|
||||
nest-app:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
container_name: Iris_app
|
||||
restart: always
|
||||
depends_on:
|
||||
- mysql
|
||||
environment:
|
||||
DATABASE_HOST: mysql
|
||||
DATABASE_PORT: 3306
|
||||
DATABASE_USER: user_crud
|
||||
DATABASE_PASSWORD: root
|
||||
DATABASE_NAME: Iris
|
||||
ports:
|
||||
- "3000:3000"
|
||||
volumes:
|
||||
mariadb_data:
|
||||
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
DB_USERNAME=
|
||||
DB_DATABASE=
|
||||
DB_PASSWORD=
|
||||
DB_PORT=
|
||||
DB_HOST=
|
||||
PORT=
|
||||
JWT=
|
||||
CARPETA=
|
||||
MAIL_URL=
|
||||
MAIL_TOKEN=
|
||||
ESCOLARES=
|
||||
ESCOLARES_PASS=
|
||||
File diff suppressed because one or more lines are too long
Generated
+924
-1048
File diff suppressed because it is too large
Load Diff
+3
-1
@@ -8,7 +8,7 @@
|
||||
"scripts": {
|
||||
"build": "nest build",
|
||||
"format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
|
||||
"start": "nest start",
|
||||
"start": "source ~/.nvm/nvm.sh && nvm use 22.10.0 && npm install && nest start",
|
||||
"start:dev": "nest start --watch",
|
||||
"start:debug": "nest start --debug --watch",
|
||||
"start:prod": "node dist/main",
|
||||
@@ -28,6 +28,7 @@
|
||||
"@nestjs/mapped-types": "*",
|
||||
"@nestjs/passport": "^11.0.5",
|
||||
"@nestjs/platform-express": "^11.1.6",
|
||||
"@nestjs/schedule": "^6.1.0",
|
||||
"@nestjs/typeorm": "^11.0.0",
|
||||
"argon2": "^0.44.0",
|
||||
"axios": "^1.12.2",
|
||||
@@ -59,6 +60,7 @@
|
||||
"@swc/core": "^1.13.5",
|
||||
"@types/express": "^5.0.3",
|
||||
"@types/jest": "^30.0.0",
|
||||
"@types/moment": "^2.11.29",
|
||||
"@types/multer": "^2.0.0",
|
||||
"@types/node": "^24.5.2",
|
||||
"@types/supertest": "^6.0.3",
|
||||
|
||||
Binary file not shown.
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,9 @@
|
||||
numeroCuenta,nombre,licenciatura,correo,fechaInicio,fechaFin,fechaLiberacion,institucion,dependencia,programa,profesor,clave,status
|
||||
315040357,RAMIREZ AVILA MELANY BETSABE,LIC. EN HISTORIA,424018289@pcpuma.acatlan.unam.mx,29/7/2024,3/12/2025,"",Instituto Nacional De Antropologia E Historia,Museo Nacional De Antropologia,"Investigación, conservación y difusión del patrimonio arqueológico y etnográfico de México","",2024-21/7-1471,Pre-Termino
|
||||
319304899,ASCENCIO DIAZ ENRIQUE,LIC. EN ACTUARIA,424018289@pcpuma.acatlan.unam.mx,27/10/2024,1/12/2025,"",UNAM,FES ACATLAN,Acatlán Contigo,Act. Jorge Carmona Mendoza,2025-12/145-24,Cancelado
|
||||
421039812,ARTEAGA GONZALEZ RUBEN MAURICIO,LIC. EN COMUNICACION,424018289@pcpuma.acatlan.unam.mx,29/12/2024,"","",UNAM,FES ACATLAN,Acatlán Contigo,MTRO. SERGIO ARTEMIO GUILLERMO VALENTÍN,2024-12/20-530,Pre-Termino
|
||||
319302187,PEREZ CENTENO JORGE,LIC. EN CIENCIAS POLITICAS Y ADMON PUB,pcentenojorge15@gmail.com,1/12/2025,8/12/2025,"",UNAM,FES ACATLAN,Acatlán Contigo,Antonio Faustino Torres,2025-12/145-24,Pre-Registro
|
||||
413076379,JIMENEZ GONZALEZ JAZMIN ALEJANDRA,LIC. EN MATEMATICAS APLICADAS Y COMP.,424018289@pcpuma.acatlan.unam.mx,1/12/2025,4/12/2025,"",UNAM,FES ACATLAN,Acatlán Contigo,xxxx,2025-12/145-24,Carta Aceptación Rechazada
|
||||
421162888,DREW IBARRA EDUARDO CARLOS,LIC. ENSEÑANZA DE ESPAÑOL(LENG. EXTRANJ),424018289@pcpuma.acatlan.unam.mx,17/12/2025,11/12/2025,"",UNIVERSIDAD NACIONAL AUTONOMA DE MEXICO,ESCUELA DE EXTENSIÓN EN CHICAGO,Enseñanza de Español como Lengua Extranjera,"",2024-12/226-2509,Pre-Termino
|
||||
419089577,GUTIERREZ GUTIERREZ DIANA ANGELICA,LIC. EN ARQUITECTURA,320154041@pcpuma.acatlan.unam.mx,19/12/2025,18/6/2026,"",UNAM,FES ACATLAN,Titulación por servicio social,LIC. MARCELA MARTÍNEZ RANGEL,2023-12/20-222,Cancelado
|
||||
422116468,CONTRERAS GONZALEZ ANA CRISTINA,LIC. EN ECONOMIA,424018289@pcpuma.acatlan.unam.mx,28/12/2025,"","",Secretaria De Agricultura Y Desarrollo Rural,Liconsa. S.a De C.v.,SERVICIO SOCIAL LICONSA OFICINA CENTRAL,"",2025-192/1-2689,Pre-Registro
|
||||
|
+32
-27
@@ -14,51 +14,56 @@ import { ServicioModule } from './servicio/servicio.module';
|
||||
import { StatusModule } from './status/status.module';
|
||||
import { TipoUsuarioModule } from './tipo-usuario/tipo-usuario.module';
|
||||
import { UsuarioModule } from './usuario/usuario.module';
|
||||
import { AuthModule } from './auth/auth.module';
|
||||
import { DriveModule } from './drive/drive.module';
|
||||
import { ScheduleModule } from '@nestjs/schedule';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
ConfigModule.forRoot(
|
||||
{isGlobal: true}
|
||||
),
|
||||
|
||||
ScheduleModule.forRoot(),
|
||||
ConfigModule.forRoot({ isGlobal: true }),
|
||||
|
||||
TypeOrmModule.forRoot({
|
||||
type: 'mysql',
|
||||
host: process.env.db_host,
|
||||
username: process.env.db_username,
|
||||
database: process.env.db_database,
|
||||
password: process.env.db_password,
|
||||
port: Number(process.env.db_port),
|
||||
synchronize: true,
|
||||
dropSchema: false, // elimina la base de datos
|
||||
// logging: true, // Habilita los logs para depuración
|
||||
autoLoadEntities: true, // Carga automáticamente las entidades
|
||||
|
||||
type: 'mariadb',
|
||||
host: process.env.DB_HOST,
|
||||
username: process.env.DB_USERNAME,
|
||||
database: process.env.DB_DATABASE,
|
||||
password: process.env.DB_PASSWORD,
|
||||
port: Number(process.env.DB_PORT),
|
||||
synchronize: false, //Lo ponemos en false para no afectar
|
||||
dropSchema: false,
|
||||
autoLoadEntities: true,
|
||||
logger: 'advanced-console',
|
||||
logging: 'all',
|
||||
}),
|
||||
|
||||
|
||||
CarreraModule,
|
||||
|
||||
|
||||
CasoEspecialModule,
|
||||
|
||||
|
||||
CuestionarioAlumnoModule,
|
||||
|
||||
|
||||
CuestionarioAlumno2Module,
|
||||
|
||||
|
||||
CuestionarioProgramaModule,
|
||||
|
||||
|
||||
CuestionarioPrograma2Module,
|
||||
|
||||
|
||||
ProgramaModule,
|
||||
|
||||
|
||||
ServicioModule,
|
||||
|
||||
|
||||
StatusModule,
|
||||
|
||||
|
||||
AuthModule,
|
||||
|
||||
TipoUsuarioModule,
|
||||
|
||||
|
||||
UsuarioModule,
|
||||
|
||||
DriveModule,
|
||||
],
|
||||
controllers: [AppController],
|
||||
providers: [AppService],
|
||||
})
|
||||
export class AppModule {}
|
||||
export class AppModule { }
|
||||
|
||||
@@ -10,7 +10,7 @@ import { AuthService } from './auth.service';
|
||||
|
||||
@Controller('auth')
|
||||
export class AuthController {
|
||||
constructor(private readonly authService: AuthService) {}
|
||||
constructor(private readonly authService: AuthService) { }
|
||||
|
||||
// ===================== LOGIN =====================
|
||||
@Post('login')
|
||||
@@ -36,4 +36,15 @@ export class AuthController {
|
||||
throw new UnauthorizedException(error.message);
|
||||
}
|
||||
}
|
||||
|
||||
// ===================== ACTUALIZAR CONTRASEÑA ADMIN =====================
|
||||
@Post('update-password')
|
||||
async updatePassword() {
|
||||
try {
|
||||
const newPassword = await this.authService.update_password();
|
||||
return { message: 'Contraseña actualizada correctamente.', contraseña: newPassword };
|
||||
} catch (error) {
|
||||
throw new UnauthorizedException(error.message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+14
-5
@@ -1,18 +1,27 @@
|
||||
import { JwtModule } from '@nestjs/jwt';
|
||||
import { JwtModule, JwtService } from '@nestjs/jwt';
|
||||
import { Module } from '@nestjs/common';
|
||||
import { AuthService } from './auth.service';
|
||||
import { Usuario } from 'src/usuario/entities/usuario.entity';
|
||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
import { AuthController } from './auth.controller';
|
||||
import { JwtStrategy } from './jwt.strategy';
|
||||
import { ConfigModule, ConfigService } from '@nestjs/config';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
ConfigModule.forRoot(),
|
||||
TypeOrmModule.forFeature([Usuario]),
|
||||
JwtModule.register({
|
||||
secret: process.env.JWT, // Usa un .env en producción
|
||||
signOptions: { expiresIn: '1h' },
|
||||
JwtModule.registerAsync({
|
||||
imports: [ConfigModule],
|
||||
useFactory: async (configService: ConfigService) => ({
|
||||
secret: configService.get('JWT') || 'clave_temporal_desarrollo',
|
||||
signOptions: { expiresIn: '1h' },
|
||||
}),
|
||||
inject: [ConfigService],
|
||||
}),
|
||||
],
|
||||
providers: [AuthService],
|
||||
controllers: [AuthController],
|
||||
providers: [AuthService, JwtStrategy],
|
||||
exports: [AuthService],
|
||||
})
|
||||
export class AuthModule {}
|
||||
|
||||
@@ -7,7 +7,6 @@ import {
|
||||
import { JwtService } from '@nestjs/jwt';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
import axios from 'axios';
|
||||
import { bcrypt } from 'bcrypt';
|
||||
|
||||
import { Carrera } from 'src/carrera/entities/carrera.entity';
|
||||
import { gmail } from 'src/helpers.services/gmail.service';
|
||||
@@ -15,6 +14,7 @@ import { Servicio } from 'src/servicio/entities/servicio.entity';
|
||||
import { Usuario } from 'src/usuario/entities/usuario.entity';
|
||||
import { Like, Not, Repository } from 'typeorm';
|
||||
import * as argon2 from 'argon2';
|
||||
import * as bcrypt from 'bcrypt';
|
||||
|
||||
@Injectable()
|
||||
export class AuthService {
|
||||
@@ -23,7 +23,7 @@ export class AuthService {
|
||||
|
||||
@InjectRepository(Usuario)
|
||||
private readonly userRepo: Repository<Usuario>,
|
||||
) {}
|
||||
) { }
|
||||
|
||||
async jwtVerificar(token: string) {
|
||||
try {
|
||||
@@ -48,7 +48,7 @@ export class AuthService {
|
||||
}
|
||||
|
||||
async comparar(password, dbPassword) {
|
||||
if (await argon2.verify(password, dbPassword)) {
|
||||
if (await bcrypt.compare(password, dbPassword)) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
@@ -56,7 +56,8 @@ export class AuthService {
|
||||
}
|
||||
|
||||
async encriptar(password) {
|
||||
return await argon2.hash(password);
|
||||
const saltRounds = 10;
|
||||
return await bcrypt.hash(password, saltRounds);
|
||||
}
|
||||
|
||||
async generarPassword() {
|
||||
@@ -72,16 +73,49 @@ export class AuthService {
|
||||
return password;
|
||||
}
|
||||
|
||||
async update_password() {
|
||||
let user = await this.userRepo.findOne({ where: { tipoUsuario: { idTipoUsuario: 1 } } })
|
||||
|
||||
if (!user) throw new NotFoundException('No se encontró el usuario administrador.');
|
||||
const newPassword = await this.generarPassword();
|
||||
const hashedPassword = await this.encriptar(newPassword);
|
||||
user.password = hashedPassword;
|
||||
await this.userRepo.save(user);
|
||||
return newPassword;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
async login(usuario: string, password: string) {
|
||||
const user = await this.userRepo.findOne({ where: { usuario } });
|
||||
const user = await this.userRepo.findOne({
|
||||
where: { usuario },
|
||||
relations: ['tipoUsuario'],
|
||||
});
|
||||
|
||||
if (!user) throw new UnauthorizedException('No existe este usuario.');
|
||||
|
||||
const match = await this.comparar(password, user.password);
|
||||
if (!match) throw new UnauthorizedException('Credenciales inválidas');
|
||||
if (!user.activo) throw new Error('Este usuario no esta activo.');
|
||||
const token = this.jwtCreate(
|
||||
|
||||
if (!user.activo) throw new BadRequestException('Este usuario no esta activo.');
|
||||
|
||||
const token = await this.jwtCreate(
|
||||
user.idUsuario,
|
||||
user.tipoUsuario.idTipoUsuario,
|
||||
);
|
||||
return token;
|
||||
|
||||
return {
|
||||
token: token.access_token,
|
||||
Usuario: {
|
||||
idUsuario: user.idUsuario,
|
||||
usuario: user.usuario,
|
||||
nombre: user.nombre || '',
|
||||
TipoUsuario: {
|
||||
idTipoUsuario: user.tipoUsuario.idTipoUsuario,
|
||||
tipoUsuario: user.tipoUsuario.tipoUsuario || '',
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,19 +1,21 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { PassportStrategy } from '@nestjs/passport';
|
||||
import { ExtractJwt, Strategy } from 'passport-jwt';
|
||||
import { ConfigService } from '@nestjs/config';
|
||||
|
||||
@Injectable()
|
||||
export class JwtStrategy extends PassportStrategy(Strategy) {
|
||||
constructor() {
|
||||
constructor(private configService: ConfigService) {
|
||||
super({
|
||||
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
|
||||
secretOrKey: process.env.JWT_SECRET,
|
||||
secretOrKey: configService.get('JWT') || 'clave_temporal_desarrollo',
|
||||
});
|
||||
}
|
||||
|
||||
async validate(payload: any) {
|
||||
// payload contiene los datos del usuario que se pusieron al generar el token
|
||||
// ejemplo: { sub: 123, email: "user@example.com" }
|
||||
return { userId: payload.sub, email: payload.email };
|
||||
return {
|
||||
userId: payload.Usuario,
|
||||
tipoUsuario: payload.tipoUsuario,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
import {
|
||||
Controller,
|
||||
Get,
|
||||
Post,
|
||||
Body,
|
||||
Patch,
|
||||
Param,
|
||||
Delete,
|
||||
} from '@nestjs/common';
|
||||
import { CarreraService } from './carrera.service';
|
||||
import { CreateCarreraDto } from './dto/create-carrera.dto';
|
||||
import { UpdateCarreraDto } from './dto/update-carrera.dto';
|
||||
|
||||
@Controller('carrera')
|
||||
export class CarreraController {
|
||||
constructor(private readonly carreraService: CarreraService) {}
|
||||
|
||||
@Post()
|
||||
create(@Body() createCarreraDto: CreateCarreraDto) {
|
||||
return this.carreraService.create(createCarreraDto);
|
||||
}
|
||||
|
||||
@Get()
|
||||
findAll() {
|
||||
return this.carreraService.findAll();
|
||||
}
|
||||
|
||||
@Get(':id')
|
||||
findOne(@Param('id') id: string) {
|
||||
return this.carreraService.findOne(+id);
|
||||
}
|
||||
|
||||
@Patch(':id')
|
||||
update(@Param('id') id: string, @Body() updateCarreraDto: UpdateCarreraDto) {
|
||||
return this.carreraService.update(+id, updateCarreraDto);
|
||||
}
|
||||
|
||||
@Delete(':id')
|
||||
remove(@Param('id') id: string) {
|
||||
return this.carreraService.remove(+id);
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,9 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
import { Carrera } from './entities/carrera.entity';
|
||||
|
||||
@Module({
|
||||
controllers: [],
|
||||
providers: [],
|
||||
exports: [],
|
||||
imports: [TypeOrmModule.forFeature([Carrera])],
|
||||
exports: [TypeOrmModule],
|
||||
})
|
||||
export class CarreraModule {}
|
||||
|
||||
@@ -1,19 +1,18 @@
|
||||
import { CasoEspecial } from "src/caso-especial/entities/caso-especial.entity";
|
||||
import { Servicio } from "src/servicio/entities/servicio.entity";
|
||||
import { Column, Entity, ManyToMany, OneToMany, PrimaryGeneratedColumn } from "typeorm";
|
||||
|
||||
import { CasoEspecial } from 'src/caso-especial/entities/caso-especial.entity';
|
||||
import { Servicio } from 'src/servicio/entities/servicio.entity';
|
||||
import { Entity, PrimaryGeneratedColumn, Column, OneToMany } from 'typeorm';
|
||||
|
||||
@Entity('carrera')
|
||||
export class Carrera {
|
||||
@PrimaryGeneratedColumn()
|
||||
idCarrera:number;
|
||||
@PrimaryGeneratedColumn({ name: 'idCarrera' })
|
||||
idCarrera: number;
|
||||
|
||||
@Column({type: 'varchar', length: 50, nullable: false})
|
||||
carrera:string;
|
||||
@Column({ type: 'varchar', length: 50 })
|
||||
carrera: string;
|
||||
|
||||
@OneToMany(()=>Servicio, (servicio)=>servicio.carrera)
|
||||
servicio:Servicio[];
|
||||
@OneToMany(() => CasoEspecial, (casoEspecial) => casoEspecial.carrera)
|
||||
casosEspeciales: CasoEspecial[];
|
||||
|
||||
@OneToMany(()=>CasoEspecial,(casoEspecial)=>casoEspecial.carrera)
|
||||
casoEspecial:CasoEspecial[];
|
||||
@OneToMany(() => Servicio, (servicio) => servicio.carrera)
|
||||
servicios: Servicio[];
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ import {
|
||||
UploadedFile,
|
||||
BadRequestException,
|
||||
Put,
|
||||
Query,
|
||||
} from '@nestjs/common';
|
||||
import { CasoEspecialService } from './caso-especial.service';
|
||||
import { CreateCasoEspecialDto } from './dto/create-caso-especial.dto';
|
||||
@@ -21,13 +22,18 @@ import { diskStorage } from 'multer';
|
||||
import { extname } from 'path';
|
||||
import * as fs from 'fs';
|
||||
import { FilterCasoEspecialDto } from './dto/filter-caso-especial.dto';
|
||||
import { DriveService } from 'src/drive/drive.service';
|
||||
import { plainToInstance } from 'class-transformer';
|
||||
|
||||
@Controller('caso-especial')
|
||||
export class CasoEspecialController {
|
||||
constructor(private readonly casoEspecialService: CasoEspecialService) {}
|
||||
constructor(private readonly casoEspecialService: CasoEspecialService,
|
||||
private drive: DriveService,
|
||||
|
||||
) { }
|
||||
|
||||
@Post()
|
||||
@UseGuards(AuthGuard('jwt')) // reemplaza verificaToken
|
||||
@UseGuards(AuthGuard('jwt'))
|
||||
@UseInterceptors(
|
||||
FileInterceptor('archivos', {
|
||||
storage: diskStorage({
|
||||
@@ -41,27 +47,42 @@ export class CasoEspecialController {
|
||||
)
|
||||
async subirArchivo(
|
||||
@UploadedFile() file: Express.Multer.File,
|
||||
@Body('alumno') alumno: CreateCasoEspecialDto,
|
||||
@Body('alumno') alumno: string, // 👈 STRING
|
||||
) {
|
||||
try {
|
||||
const data = await this.casoEspecialService.create(alumno, file.filename);
|
||||
const alumnoParsed = plainToInstance(
|
||||
CreateCasoEspecialDto,
|
||||
JSON.parse(alumno),
|
||||
);
|
||||
|
||||
return await this.casoEspecialService.create(
|
||||
alumnoParsed,
|
||||
file.filename,
|
||||
);
|
||||
} catch (err) {
|
||||
if (file?.filename) {
|
||||
fs.unlinkSync(`./server/uploads/${file.filename}`);
|
||||
}
|
||||
throw new BadRequestException(err.message);
|
||||
}
|
||||
}
|
||||
@Get('carpeta')
|
||||
async carpeta() {
|
||||
try {
|
||||
const data = await this.drive.folder('123456789');
|
||||
console.log(data);
|
||||
return {
|
||||
statusCode: 201,
|
||||
message: 'Archivo subido con éxito',
|
||||
statusCode: 200,
|
||||
data,
|
||||
};
|
||||
} catch (err) {
|
||||
// Si hay error, eliminar archivo subido
|
||||
if (file && file.filename) {
|
||||
fs.unlinkSync(`./server/uploads/${file.filename}`);
|
||||
}
|
||||
throw new BadRequestException(err.message);
|
||||
}
|
||||
}
|
||||
|
||||
@Get('servicios_especiales')
|
||||
@UseGuards(AuthGuard('jwt'))
|
||||
async getServiciosEspeciales(@Body() dtoServEsp: FilterCasoEspecialDto) {
|
||||
async getServiciosEspeciales(@Query() dtoServEsp: FilterCasoEspecialDto) {
|
||||
try {
|
||||
const data = await this.casoEspecialService.findAllFiltered(dtoServEsp);
|
||||
return {
|
||||
|
||||
@@ -16,6 +16,12 @@ import { DriveService } from 'src/drive/drive.service';
|
||||
import { Status } from 'src/status/entities/status.entity';
|
||||
import { FilterCasoEspecialDto } from './dto/filter-caso-especial.dto';
|
||||
import { arch } from 'os';
|
||||
import { SendMailDto } from 'src/helpers.services/dto/send-email.dto';
|
||||
const {
|
||||
|
||||
terminoValidado
|
||||
} = require('./../helpers.services/msjCorreos');
|
||||
|
||||
|
||||
@Injectable()
|
||||
export class CasoEspecialService {
|
||||
@@ -31,7 +37,7 @@ export class CasoEspecialService {
|
||||
private validacion: ValidacionService,
|
||||
private gmail: gmail,
|
||||
private drive: DriveService,
|
||||
) {}
|
||||
) { }
|
||||
|
||||
async create(body: CreateCasoEspecialDto, file: string) {
|
||||
const {
|
||||
@@ -51,71 +57,69 @@ export class CasoEspecialService {
|
||||
motivo = '',
|
||||
} = body;
|
||||
|
||||
const usuario = await this.usuarioRepository.findOneBy({
|
||||
idUsuario: idUsuario,
|
||||
const usuario = await this.usuarioRepository.findOne({
|
||||
where: { idUsuario },
|
||||
relations: ['tipoUsuario'],
|
||||
});
|
||||
|
||||
if (!usuario)
|
||||
throw new NotFoundException('Este alumno no existe en la db.');
|
||||
if (usuario.tipoUsuario.idTipoUsuario !== 3)
|
||||
throw new BadRequestException('Este usuario no es de tipo Alumno.');
|
||||
|
||||
const carrera = await this.carreraRepository.findOneBy({
|
||||
idCarrera: idCarrera,
|
||||
});
|
||||
const carrera = await this.carreraRepository.findOneBy({ idCarrera });
|
||||
if (!carrera)
|
||||
throw new NotFoundException('Esta carrera no existe en la db.');
|
||||
|
||||
const casoExistente = await this.casoEspecialRepository.findOne({
|
||||
where: { usuario: usuario },
|
||||
where: { usuario: { idUsuario } },
|
||||
});
|
||||
if (casoExistente)
|
||||
throw new BadRequestException('Este alumno ya tiene un Caso Especial.');
|
||||
|
||||
const path = `./server/uploads/${file}`;
|
||||
const carpeta = await this.drive.folder(numeroCuenta);
|
||||
if (!carpeta) {
|
||||
throw new Error('No se pudo crear la carpeta en Drive.');
|
||||
}
|
||||
if (!carpeta) throw new BadRequestException('No se pudo crear la carpeta en Drive.');
|
||||
|
||||
const archivoZip = await this.drive.uploadFile(
|
||||
path,
|
||||
`archivos.zip`,
|
||||
'archivos.zip',
|
||||
'application/zip',
|
||||
carpeta,
|
||||
);
|
||||
if (!archivoZip)
|
||||
throw new BadRequestException('No se pudo subir el archivo a Drive.');
|
||||
|
||||
const status = await this.statusRepository.findOne({
|
||||
where: { idStatus: idStatus },
|
||||
});
|
||||
|
||||
if (!status) throw new NotFoundException('Este status no existe en la db.');
|
||||
if (archivoZip === null)
|
||||
throw new Error('No se pudo subir el archivo a Drive.');
|
||||
const status = await this.statusRepository.findOneBy({ idStatus });
|
||||
if (!status)
|
||||
throw new NotFoundException('Este status no existe en la db.');
|
||||
|
||||
const nuevoCaso = this.casoEspecialRepository.create({
|
||||
correo: correo,
|
||||
telefono: telefono,
|
||||
institucion: institucion,
|
||||
dependencia: dependencia,
|
||||
motivo: motivo,
|
||||
direccion: direccion,
|
||||
fechaInicio: fechaInicio,
|
||||
fechaFin: fechaFin,
|
||||
fechaNacimiento: fechaNacimiento,
|
||||
carpeta: carpeta,
|
||||
archivoZip: archivoZip,
|
||||
usuario: usuario,
|
||||
carrera: carrera,
|
||||
status: status,
|
||||
creditos: creditos,
|
||||
correo,
|
||||
telefono,
|
||||
institucion,
|
||||
dependencia,
|
||||
motivo,
|
||||
direccion,
|
||||
fechaInicio,
|
||||
fechaFin,
|
||||
fechaNacimiento,
|
||||
carpeta,
|
||||
archivoZip,
|
||||
usuario,
|
||||
carrera,
|
||||
status,
|
||||
creditos,
|
||||
});
|
||||
|
||||
await this.casoEspecialRepository.save(nuevoCaso);
|
||||
|
||||
let caso_especial = await this.casoEspecialRepository.save(nuevoCaso);
|
||||
console.log('Nuevo Caso Especial creado:', caso_especial);
|
||||
return {
|
||||
message: 'Se ha registrado el Caso Especial correctamente.',
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
async findAllFiltered(dto: FilterCasoEspecialDto) {
|
||||
const { pagina = 1, idStatus, nombre = '', numeroCuenta = '' } = dto;
|
||||
|
||||
@@ -138,11 +142,11 @@ export class CasoEspecialService {
|
||||
}
|
||||
|
||||
if (nombre) {
|
||||
query.andWhere('usuario.nombre ILIKE :nombre', { nombre: `%${nombre}%` });
|
||||
query.andWhere('usuario.nombre LIKE :nombre', { nombre: `%${nombre}%` });
|
||||
}
|
||||
|
||||
if (numeroCuenta) {
|
||||
query.andWhere('usuario.usuario ILIKE :numeroCuenta', {
|
||||
query.andWhere('usuario.usuario LIKE :numeroCuenta', {
|
||||
numeroCuenta: `%${numeroCuenta}%`,
|
||||
});
|
||||
}
|
||||
@@ -164,11 +168,11 @@ export class CasoEspecialService {
|
||||
|
||||
const caso = await this.casoEspecialRepository.findOne({
|
||||
where: { idCasoEspecial },
|
||||
relations: ['usuario'],
|
||||
relations: ['usuario', 'status'],
|
||||
});
|
||||
|
||||
if (!caso) {
|
||||
throw new Error('No existe este Caso Especial.');
|
||||
throw new BadRequestException('No existe este Caso Especial.');
|
||||
}
|
||||
|
||||
switch (caso.status.idStatus) {
|
||||
@@ -177,11 +181,10 @@ export class CasoEspecialService {
|
||||
const correo = terminoValidado(caso.usuario.nombre);
|
||||
|
||||
// Actualiza el status según el caso
|
||||
update = {
|
||||
idStatus: caso.status.idStatus === 11 ? 13 : 14,
|
||||
};
|
||||
caso.status.idStatus = caso.status.idStatus === 11 ? 13 : 14;
|
||||
await this.casoEspecialRepository.save(caso);
|
||||
|
||||
let sendcorreo = {
|
||||
let sendMessage: SendMailDto = {
|
||||
to: caso.correo,
|
||||
|
||||
subject: correo.subject,
|
||||
@@ -193,18 +196,16 @@ export class CasoEspecialService {
|
||||
};
|
||||
|
||||
// Envía correo
|
||||
await this.gmail.enviarCorreo(sendcorreo);
|
||||
await this.gmail.enviarCorreo(sendMessage);
|
||||
break;
|
||||
|
||||
case 6:
|
||||
throw new Error('Este Caso Especial ya se encuentra en Liberación.');
|
||||
throw new BadRequestException('Este Caso Especial ya se encuentra en Liberación.');
|
||||
|
||||
default:
|
||||
throw new Error('Id status no válido.');
|
||||
throw new BadRequestException('Id status no válido.');
|
||||
}
|
||||
|
||||
// Actualiza en base de datos
|
||||
await this.casoEspecialRepository.update({ idCasoEspecial }, update);
|
||||
|
||||
return {
|
||||
message:
|
||||
@@ -223,9 +224,9 @@ export class CasoEspecialService {
|
||||
relations: ['usuario', 'carrera', 'status'],
|
||||
});
|
||||
if (!casoEspecial) {
|
||||
throw new Error('No existe este Caso Especial.');
|
||||
throw new BadRequestException('No existe este Caso Especial.');
|
||||
}
|
||||
return casoEspecial.createdAt;
|
||||
return casoEspecial;
|
||||
}
|
||||
|
||||
async updateCasoEspecial(id: number, dto: UpdateCasoEspecialDto) {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { Type } from 'class-transformer';
|
||||
import {
|
||||
IsEmail,
|
||||
IsNotEmpty,
|
||||
@@ -13,19 +14,19 @@ import {
|
||||
} from 'class-validator';
|
||||
|
||||
export class CreateCasoEspecialDto {
|
||||
@Type(() => Number)
|
||||
@IsNumber()
|
||||
idUsuario: number;
|
||||
|
||||
@IsNumber()
|
||||
@Type(() => Number)
|
||||
@IsInt()
|
||||
idCarrera: number;
|
||||
|
||||
@Type(() => Number)
|
||||
@IsNumber()
|
||||
@Length(1, 11)
|
||||
idStatus: number;
|
||||
|
||||
@IsString()
|
||||
@Length(9, 9)
|
||||
@Matches(/^\d+$/, { message: 'solo puede contener números' })
|
||||
numeroCuenta: string;
|
||||
|
||||
|
||||
@@ -14,15 +14,15 @@ export class UpdateCasoEspecialDto {
|
||||
|
||||
@IsOptional()
|
||||
@IsDateString()
|
||||
fechaInicio?: Date;
|
||||
fechaInicio?: string;
|
||||
|
||||
@IsOptional()
|
||||
@IsDateString()
|
||||
fechaFin?: Date;
|
||||
fechaFin?: string;
|
||||
|
||||
@IsOptional()
|
||||
@IsDateString()
|
||||
fechaNacimiento?: Date;
|
||||
fechaNacimiento?: string;
|
||||
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
|
||||
@@ -1,63 +1,74 @@
|
||||
import { Carrera } from "src/carrera/entities/carrera.entity";
|
||||
import { Status } from "src/status/entities/status.entity";
|
||||
import { Usuario } from "src/usuario/entities/usuario.entity";
|
||||
import { Column, Entity, ManyToMany, ManyToOne, PrimaryGeneratedColumn } from "typeorm";
|
||||
import {
|
||||
Entity,
|
||||
PrimaryGeneratedColumn,
|
||||
Column,
|
||||
ManyToOne,
|
||||
JoinColumn,
|
||||
CreateDateColumn,
|
||||
UpdateDateColumn,
|
||||
} from 'typeorm';
|
||||
|
||||
import { Carrera } from 'src/carrera/entities/carrera.entity';
|
||||
import { Status } from 'src/status/entities/status.entity';
|
||||
import { Usuario } from 'src/usuario/entities/usuario.entity';
|
||||
|
||||
@Entity('caso_especial')
|
||||
export class CasoEspecial {
|
||||
@PrimaryGeneratedColumn()
|
||||
idCasoEspecial: number;
|
||||
@PrimaryGeneratedColumn({ name: 'idCasoEspecial' })
|
||||
idCasoEspecial: number;
|
||||
|
||||
@Column({ type: 'varchar', length: 3 })
|
||||
creditos: string;
|
||||
@Column({ name: 'creditos', type: 'varchar', length: 3, nullable: false })
|
||||
creditos: string;
|
||||
|
||||
@Column({ type: 'varchar', length: 60 })
|
||||
correo: string;
|
||||
@Column({ name: 'correo', type: 'varchar', length: 60, nullable: false })
|
||||
correo: string;
|
||||
|
||||
@Column({ type: 'varchar', length: 15 })
|
||||
telefono: string;
|
||||
@Column({ name: 'telefono', type: 'varchar', length: 15, nullable: false })
|
||||
telefono: string;
|
||||
|
||||
@Column({ type: 'varchar', length: 200, nullable: true, default: null })
|
||||
institucion: string | null;
|
||||
@Column({ name: 'institucion', type: 'varchar', length: 200, nullable: true })
|
||||
institucion?: string;
|
||||
|
||||
@Column({ type: 'varchar', length: 200, nullable: true, default: null })
|
||||
dependencia: string | null;
|
||||
@Column({ name: 'dependencia', type: 'varchar', length: 200, nullable: true })
|
||||
dependencia?: string;
|
||||
|
||||
@Column({ type: 'varchar', length: 1, nullable: true, default: null })
|
||||
motivo: string | null;
|
||||
@Column({ name: 'motivo', type: 'varchar', length: 1, nullable: true })
|
||||
motivo?: string;
|
||||
|
||||
@Column({ type: 'varchar', length: 200 })
|
||||
direccion: string;
|
||||
@Column({ name: 'direccion', type: 'varchar', length: 200, nullable: false })
|
||||
direccion: string;
|
||||
|
||||
@Column({ type: 'timestamp' })
|
||||
fechaInicio: Date;
|
||||
@Column({ name: 'fechaInicio', type: 'date', nullable: false })
|
||||
fechaInicio: string;
|
||||
|
||||
@Column({ type: 'timestamp' })
|
||||
fechaFin: Date;
|
||||
@Column({ name: 'fechaFin', type: 'date', nullable: false })
|
||||
fechaFin: string;
|
||||
|
||||
@Column({ type: 'timestamp' })
|
||||
fechaNacimiento: Date;
|
||||
@Column({ name: 'fechaNacimiento', type: 'date', nullable: false })
|
||||
fechaNacimiento: string;
|
||||
|
||||
@Column({ type: 'varchar', length: 60 })
|
||||
carpeta: string;
|
||||
@Column({ name: 'carpeta', type: 'varchar', length: 60, nullable: false })
|
||||
carpeta: string;
|
||||
|
||||
@Column({ type: 'varchar', length: 60 })
|
||||
archivoZip: string;
|
||||
|
||||
@Column({ type: 'timestamp', default: () => 'CURRENT_TIMESTAMP' })
|
||||
createdAt: Date;
|
||||
@Column({ name: 'archivoZip', type: 'varchar', length: 60, nullable: false })
|
||||
archivoZip: string;
|
||||
|
||||
@Column({ type: 'timestamp', default: () => 'CURRENT_TIMESTAMP', onUpdate: 'CURRENT_TIMESTAMP' })
|
||||
updatedAt: Date;
|
||||
@CreateDateColumn({ name: 'createdAt', type: 'datetime' })
|
||||
createdAt: Date;
|
||||
|
||||
@ManyToOne(()=>Usuario, (usuario)=>usuario.casoEspecial)
|
||||
usuario:Usuario;
|
||||
@UpdateDateColumn({ name: 'updatedAt', type: 'datetime' })
|
||||
updatedAt: Date;
|
||||
|
||||
@ManyToOne(()=>Carrera, (carrera)=>carrera.casoEspecial)
|
||||
carrera:Carrera;
|
||||
|
||||
@ManyToOne(()=>Status, (status)=>status.casoEspecial)
|
||||
status:Status;
|
||||
// ===== Relaciones =====
|
||||
@ManyToOne(() => Usuario, (usuario) => usuario.casoEspecial) //error en el nombre al llamar caso especial (se cambio)
|
||||
@JoinColumn({ name: 'idUsuario' })
|
||||
usuario: Usuario;
|
||||
|
||||
@ManyToOne(() => Carrera, (carrera) => carrera.casosEspeciales)
|
||||
@JoinColumn({ name: 'idCarrera' })
|
||||
carrera: Carrera;
|
||||
|
||||
@ManyToOne(() => Status, (status) => status.casoEspecial) //error en el nombre al llamar caso especial (se cambio)
|
||||
@JoinColumn({ name: 'idStatus' })
|
||||
status: Status;
|
||||
}
|
||||
|
||||
@@ -1,111 +1,124 @@
|
||||
import { Servicio } from "src/servicio/entities/servicio.entity";
|
||||
import { Column, Entity, OneToMany, PrimaryGeneratedColumn } from "typeorm";
|
||||
import { Servicio } from 'src/servicio/entities/servicio.entity';
|
||||
import {
|
||||
Entity,
|
||||
PrimaryGeneratedColumn,
|
||||
Column,
|
||||
CreateDateColumn,
|
||||
OneToMany,
|
||||
} from 'typeorm';
|
||||
|
||||
@Entity('cuestionario_alumno')
|
||||
export class CuestionarioAlumno {
|
||||
@PrimaryGeneratedColumn()
|
||||
idCuestionarioAlumno: number;
|
||||
@PrimaryGeneratedColumn({ name: 'idCuestionarioAlumno' })
|
||||
idCuestionarioAlumno: number;
|
||||
|
||||
@Column({ type: 'varchar', length: 1 })
|
||||
sexo: string;
|
||||
@Column({ name: 'sexo', type: 'varchar', length: 1, nullable: false })
|
||||
sexo: string;
|
||||
|
||||
@Column({ type: 'varchar', length: 2 })
|
||||
edad: string;
|
||||
@Column({ name: 'edad', type: 'varchar', length: 2, nullable: false })
|
||||
edad: string;
|
||||
|
||||
@Column({ type: 'varchar', length: 100 })
|
||||
servicioMedico: string;
|
||||
@Column({
|
||||
name: 'servicioMedico',
|
||||
type: 'varchar',
|
||||
length: 100,
|
||||
nullable: false,
|
||||
})
|
||||
servicioMedico: string;
|
||||
|
||||
@Column()
|
||||
p1: boolean;
|
||||
@Column({ name: 'p1', type: 'tinyint', width: 1, nullable: false })
|
||||
p1: boolean;
|
||||
|
||||
@Column()
|
||||
p2: boolean;
|
||||
@Column({ name: 'p2', type: 'tinyint', width: 1, nullable: false })
|
||||
p2: boolean;
|
||||
|
||||
@Column({ type: 'varchar', length: 150 })
|
||||
p3: string;
|
||||
@Column({ name: 'p3', type: 'varchar', length: 150, nullable: false })
|
||||
p3: string;
|
||||
|
||||
@Column()
|
||||
p4: boolean;
|
||||
@Column({ name: 'p4', type: 'tinyint', width: 1, nullable: false })
|
||||
p4: boolean;
|
||||
|
||||
@Column({ type: 'varchar', length: 7 })
|
||||
p5: string;
|
||||
@Column({ name: 'p5', type: 'varchar', length: 7, nullable: false })
|
||||
p5: string;
|
||||
|
||||
@Column()
|
||||
p6: boolean;
|
||||
@Column({ name: 'p6', type: 'tinyint', width: 1, nullable: false })
|
||||
p6: boolean;
|
||||
|
||||
@Column()
|
||||
p7: boolean;
|
||||
@Column({ name: 'p7', type: 'tinyint', width: 1, nullable: false })
|
||||
p7: boolean;
|
||||
|
||||
@Column({ type: 'varchar', length: 5 })
|
||||
p8: string;
|
||||
@Column({ name: 'p8', type: 'varchar', length: 5, nullable: false })
|
||||
p8: string;
|
||||
|
||||
@Column()
|
||||
p9: boolean;
|
||||
@Column({ name: 'p9', type: 'tinyint', width: 1, nullable: false })
|
||||
p9: boolean;
|
||||
|
||||
@Column()
|
||||
p10: boolean;
|
||||
@Column({ name: 'p10', type: 'tinyint', width: 1, nullable: false })
|
||||
p10: boolean;
|
||||
|
||||
@Column()
|
||||
p11: boolean;
|
||||
@Column({ name: 'p11', type: 'tinyint', width: 1, nullable: false })
|
||||
p11: boolean;
|
||||
|
||||
@Column()
|
||||
p12: boolean;
|
||||
@Column({ name: 'p12', type: 'tinyint', width: 1, nullable: false })
|
||||
p12: boolean;
|
||||
|
||||
@Column()
|
||||
p13: boolean;
|
||||
@Column({ name: 'p13', type: 'tinyint', width: 1, nullable: false })
|
||||
p13: boolean;
|
||||
|
||||
@Column({ type: 'varchar', length: 7 })
|
||||
p14: string;
|
||||
@Column({ name: 'p14', type: 'varchar', length: 7, nullable: false })
|
||||
p14: string;
|
||||
|
||||
@Column({ type: 'varchar', length: 7 })
|
||||
p15: string;
|
||||
@Column({ name: 'p15', type: 'varchar', length: 7, nullable: false })
|
||||
p15: string;
|
||||
|
||||
@Column({ type: 'varchar', length: 2 })
|
||||
p16: string;
|
||||
@Column({ name: 'p16', type: 'varchar', length: 2, nullable: false })
|
||||
p16: string;
|
||||
|
||||
@Column({ type: 'varchar', length: 5 })
|
||||
p17: string;
|
||||
@Column({ name: 'p17', type: 'varchar', length: 5, nullable: false })
|
||||
p17: string;
|
||||
|
||||
@Column()
|
||||
p18: boolean;
|
||||
@Column({ name: 'p18', type: 'tinyint', width: 1, nullable: false })
|
||||
p18: boolean;
|
||||
|
||||
@Column()
|
||||
p19: boolean;
|
||||
@Column({ name: 'p19', type: 'tinyint', width: 1, nullable: false })
|
||||
p19: boolean;
|
||||
|
||||
@Column()
|
||||
p20: boolean;
|
||||
@Column({ name: 'p20', type: 'tinyint', width: 1, nullable: false })
|
||||
p20: boolean;
|
||||
|
||||
@Column({ type: 'varchar', length: 9 })
|
||||
p21: string;
|
||||
@Column({ name: 'p21', type: 'varchar', length: 9, nullable: false })
|
||||
p21: string;
|
||||
|
||||
@Column({ type: 'varchar', length: 23 })
|
||||
p22: string;
|
||||
@Column({ name: 'p22', type: 'varchar', length: 23, nullable: false })
|
||||
p22: string;
|
||||
|
||||
@Column({ type: 'varchar', length: 8 })
|
||||
p23: string;
|
||||
@Column({ name: 'p23', type: 'varchar', length: 8, nullable: false })
|
||||
p23: string;
|
||||
|
||||
@Column({ type: 'varchar', length: 8 })
|
||||
p24: string;
|
||||
@Column({ name: 'p24', type: 'varchar', length: 8, nullable: false })
|
||||
p24: string;
|
||||
|
||||
@Column()
|
||||
p25: boolean;
|
||||
@Column({ name: 'p25', type: 'tinyint', width: 1, nullable: false })
|
||||
p25: boolean;
|
||||
|
||||
@Column()
|
||||
p26: boolean;
|
||||
@Column({ name: 'p26', type: 'tinyint', width: 1, nullable: false })
|
||||
p26: boolean;
|
||||
|
||||
@Column({ type: 'varchar', length: 400 })
|
||||
p27: string;
|
||||
@Column({ name: 'p27', type: 'varchar', length: 400, nullable: false })
|
||||
p27: string;
|
||||
|
||||
@Column({ type: 'varchar', length: 1 })
|
||||
p28: string;
|
||||
@Column({ name: 'p28', type: 'varchar', length: 1, nullable: false })
|
||||
p28: string;
|
||||
|
||||
@Column({ type: 'varchar', length: 1 })
|
||||
p29: string;
|
||||
@Column({ name: 'p29', type: 'varchar', length: 1, nullable: false })
|
||||
p29: string;
|
||||
|
||||
@Column({ type: 'varchar', length: 400 })
|
||||
p30: string;
|
||||
@Column({ name: 'p30', type: 'varchar', length: 400, nullable: false })
|
||||
p30: string;
|
||||
|
||||
@OneToMany(()=>Servicio,(servicio)=>servicio.cuestionarioAlumno2)
|
||||
servicio:Servicio[];
|
||||
@CreateDateColumn({ name: 'createdAt', type: 'datetime' })
|
||||
createdAt: Date;
|
||||
|
||||
@OneToMany(() => Servicio, (servicio) => servicio.cuestionarioAlumno2)
|
||||
servicio: Servicio[];
|
||||
}
|
||||
|
||||
@@ -7,12 +7,15 @@ import {
|
||||
Param,
|
||||
Delete,
|
||||
UseGuards,
|
||||
Query,
|
||||
Res,
|
||||
} from '@nestjs/common';
|
||||
import { CuestionarioAlumno2Service } from './cuestionario-alumno2.service';
|
||||
import { CreateCuestionarioAlumno2Dto } from './dto/create-cuestionario-alumno2.dto';
|
||||
|
||||
import { AuthGuard } from '@nestjs/passport';
|
||||
import { findCuestionarioAlumno2Dto } from './dto/find.dto';
|
||||
import { Response } from 'express';
|
||||
|
||||
@Controller('cuestionario-alumno2')
|
||||
export class CuestionarioAlumno2Controller {
|
||||
@@ -23,13 +26,18 @@ export class CuestionarioAlumno2Controller {
|
||||
@Post()
|
||||
@UseGuards(AuthGuard('jwt'))
|
||||
create(@Body() createCuestionarioAlumno2Dto: CreateCuestionarioAlumno2Dto) {
|
||||
|
||||
console.log('CreateCuestionarioAlumno2Dto recibido:', createCuestionarioAlumno2Dto);
|
||||
|
||||
return this.cuestionarioAlumno2Service.create(createCuestionarioAlumno2Dto);
|
||||
}
|
||||
|
||||
@Get()
|
||||
@UseGuards(AuthGuard('jwt'))
|
||||
findAll(@Body() findDto: findCuestionarioAlumno2Dto) {
|
||||
return this.cuestionarioAlumno2Service.get(findDto.version, findDto.anio);
|
||||
async findAll(@Query() findDto: findCuestionarioAlumno2Dto, @Res() res: Response) {
|
||||
const path = await this.cuestionarioAlumno2Service.get(findDto.version, findDto.anio);
|
||||
|
||||
return res.download(path);
|
||||
}
|
||||
|
||||
// @Get(':id')
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { BadRequestException, Injectable } from '@nestjs/common';
|
||||
import { CreateCuestionarioAlumno2Dto } from './dto/create-cuestionario-alumno2.dto';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
import { Servicio } from 'src/servicio/entities/servicio.entity';
|
||||
@@ -21,7 +21,7 @@ export class CuestionarioAlumno2Service {
|
||||
private cuestionarioAlumnoRepository: Repository<CuestionarioAlumno>,
|
||||
private validacionService: ValidacionService,
|
||||
private archivoService: ArchivoService,
|
||||
) {}
|
||||
) { }
|
||||
|
||||
async create(createCuestionarioAlumno2Dto: CreateCuestionarioAlumno2Dto) {
|
||||
let idServicio = createCuestionarioAlumno2Dto.idServicio;
|
||||
@@ -32,13 +32,14 @@ export class CuestionarioAlumno2Service {
|
||||
|
||||
let servicio = await this.servicioRepository.findOne({
|
||||
where: { idServicio },
|
||||
relations: ['cuestionarioAlumno2', 'status'],
|
||||
});
|
||||
if (!servicio) {
|
||||
throw new Error('No existe este Servicio Social.');
|
||||
throw new BadRequestException('No existe este Servicio Social.');
|
||||
}
|
||||
|
||||
if (servicio.cuestionarioAlumno2.idCuestionarioAlumno2) {
|
||||
throw new Error(
|
||||
if (servicio.cuestionarioAlumno2) {
|
||||
throw new BadRequestException(
|
||||
'Este Servicio Social ya cuenta con cuestionario de alumno',
|
||||
);
|
||||
}
|
||||
@@ -48,7 +49,7 @@ export class CuestionarioAlumno2Service {
|
||||
console.log('antes de create ques2');
|
||||
|
||||
if (messageByStatus.hasOwnProperty(servicio.status.idStatus)) {
|
||||
throw new Error(messageByStatus[servicio.status.idStatus]);
|
||||
throw new BadRequestException(messageByStatus[servicio.status.idStatus]);
|
||||
}
|
||||
|
||||
console.log('datos a registrar en la tabla cuestionarioAlumno2', {
|
||||
@@ -66,44 +67,87 @@ export class CuestionarioAlumno2Service {
|
||||
{ cuestionarioAlumno2: respuestasRegistradas },
|
||||
);
|
||||
|
||||
await this.validacionService.validarPreTermino(idServicio)
|
||||
|
||||
return resX;
|
||||
}
|
||||
|
||||
async get(version: string, anio: string) {
|
||||
const year = anio;
|
||||
const path = `server/uploads/${year}_cuestionario_alumno.csv`;
|
||||
/*
|
||||
async get(version: string, anio: string) {
|
||||
const year = anio;
|
||||
const path = `server/uploads/${year}_cuestionario_alumno.csv`;
|
||||
|
||||
let data = [];
|
||||
|
||||
console.log(year);
|
||||
let temp;
|
||||
|
||||
if (version == 'v1') {
|
||||
temp = await this.cuestionarioAlumnoRepository.find({
|
||||
where: {
|
||||
idCuestionarioAlumno: Not(IsNull()),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
if (version == 'v2') {
|
||||
temp = await this.cuestionarioAlumno2Repository.find({
|
||||
where: {
|
||||
idCuestionarioAlumno2: Not(IsNull()),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
if (!temp) {
|
||||
throw new BadRequestException();
|
||||
}
|
||||
|
||||
data = temp.map((item) => ({ ...item }));
|
||||
|
||||
await this.archivoService.eliminarArchivo(path).catch((err) => {
|
||||
console.log(err);
|
||||
});
|
||||
|
||||
return this.archivoService.crearArchivo(path, convertArrayToCSV(data));
|
||||
}
|
||||
*/
|
||||
async get(version: string, anio: string): Promise<string> {
|
||||
const path = `server/uploads/${anio}_cuestionario_alumno.csv`;
|
||||
|
||||
let data = [];
|
||||
|
||||
console.log(year);
|
||||
let temp;
|
||||
|
||||
if (version == 'v1') {
|
||||
temp = this.cuestionarioAlumnoRepository.find({
|
||||
if (version === 'v1') {
|
||||
temp = await this.cuestionarioAlumnoRepository.find({
|
||||
where: {
|
||||
idCuestionarioAlumno: Not(IsNull()),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
if (version == 'v2') {
|
||||
temp = this.cuestionarioAlumno2Repository.find({
|
||||
if (version === 'v2') {
|
||||
temp = await this.cuestionarioAlumno2Repository.find({
|
||||
where: {
|
||||
idCuestionarioAlumno2: Not(IsNull()),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
if (!temp) {
|
||||
throw new Error();
|
||||
if (!temp || temp.length === 0) {
|
||||
throw new BadRequestException('No hay datos para exportar');
|
||||
}
|
||||
|
||||
data = temp.map((item) => ({ ...item }));
|
||||
const data = temp.map((item) => ({ ...item }));
|
||||
|
||||
await this.archivoService.eliminarArchivo(path).catch((err) => {
|
||||
console.log(err);
|
||||
});
|
||||
await this.archivoService.eliminarArchivo(path).catch(() => null);
|
||||
|
||||
return this.archivoService.crearArchivo(path, convertArrayToCSV(data));
|
||||
// ✅ Creamos el archivo
|
||||
await this.archivoService.crearArchivo(
|
||||
path,
|
||||
convertArrayToCSV(data),
|
||||
);
|
||||
|
||||
// ✅ SOLO regresamos el path
|
||||
return path;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ export class CreateCuestionarioAlumno2Dto {
|
||||
|
||||
@IsNumber()
|
||||
@IsNotEmpty()
|
||||
idServicio:number
|
||||
idServicio: number
|
||||
|
||||
|
||||
@IsString()
|
||||
@@ -134,6 +134,10 @@ export class CreateCuestionarioAlumno2Dto {
|
||||
@IsNotEmpty()
|
||||
p12_C_4: string;
|
||||
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
p12_C_5: string;
|
||||
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
p12_D_1: string;
|
||||
|
||||
@@ -1,145 +1,143 @@
|
||||
import { Servicio } from "src/servicio/entities/servicio.entity";
|
||||
import { Column, Entity, OneToMany, PrimaryGeneratedColumn } from "typeorm";
|
||||
import { Servicio } from 'src/servicio/entities/servicio.entity';
|
||||
import { Column, Entity, OneToMany, PrimaryGeneratedColumn } from 'typeorm';
|
||||
|
||||
@Entity('cuestionario_alumno_2')
|
||||
export class CuestionarioAlumno2 {
|
||||
|
||||
@PrimaryGeneratedColumn()
|
||||
idCuestionarioAlumno2: number;
|
||||
|
||||
@Column({ type: 'varchar', length: 100, nullable: false })
|
||||
@Column({ type: 'text', nullable: true })
|
||||
p1: string;
|
||||
|
||||
@Column({ type: 'varchar', length: 50, nullable: false })
|
||||
@Column({ type: 'varchar', length: 200, nullable: true })
|
||||
p2: string;
|
||||
|
||||
@Column({ type: 'varchar', length: 5, nullable: false })
|
||||
@Column({ type: 'varchar', length: 200, nullable: true })
|
||||
p4: string;
|
||||
|
||||
@Column({ type: 'varchar', length: 50, nullable: true })
|
||||
@Column({ type: 'varchar', length: 500, nullable: true })
|
||||
p5: string;
|
||||
|
||||
@Column({ type: 'varchar', length: 5, nullable: false })
|
||||
@Column({ type: 'varchar', length: 200, nullable: true })
|
||||
p6: string;
|
||||
|
||||
@Column({ type: 'varchar', length: 5, nullable: false })
|
||||
@Column({ type: 'varchar', length: 200, nullable: true })
|
||||
p7: string;
|
||||
|
||||
@Column({ type: 'varchar', length: 50, nullable: true })
|
||||
@Column({ type: 'varchar', length: 500, nullable: true })
|
||||
p8: string;
|
||||
|
||||
@Column({ type: 'varchar', length: 5, nullable: false })
|
||||
@Column({ type: 'varchar', length: 200, nullable: true })
|
||||
p9: string;
|
||||
|
||||
@Column({ type: 'varchar', length: 5, nullable: false })
|
||||
@Column({ type: 'varchar', length: 50, nullable: true })
|
||||
p3_1: string;
|
||||
|
||||
@Column({ type: 'varchar', length: 5, nullable: false })
|
||||
@Column({ type: 'varchar', length: 50, nullable: true })
|
||||
p3_2: string;
|
||||
|
||||
@Column({ type: 'varchar', length: 5, nullable: false })
|
||||
@Column({ type: 'varchar', length: 50, nullable: true })
|
||||
p3_3: string;
|
||||
|
||||
@Column({ type: 'varchar', length: 5, nullable: false })
|
||||
@Column({ type: 'varchar', length: 50, nullable: true })
|
||||
p3_4: string;
|
||||
|
||||
@Column({ type: 'varchar', length: 5, nullable: false })
|
||||
@Column({ type: 'varchar', length: 20, nullable: true })
|
||||
p10_1: string;
|
||||
|
||||
@Column({ type: 'varchar', length: 5, nullable: false })
|
||||
@Column({ type: 'varchar', length: 20, nullable: true })
|
||||
p10_2: string;
|
||||
|
||||
@Column({ type: 'varchar', length: 5, nullable: false })
|
||||
@Column({ type: 'varchar', length: 20, nullable: true })
|
||||
p10_3: string;
|
||||
|
||||
@Column({ type: 'varchar', length: 20, nullable: false })
|
||||
@Column({ type: 'varchar', length: 20, nullable: true })
|
||||
p11_1: string;
|
||||
|
||||
@Column({ type: 'varchar', length: 20, nullable: false })
|
||||
@Column({ type: 'varchar', length: 20, nullable: true })
|
||||
p11_2: string;
|
||||
|
||||
@Column({ type: 'varchar', length: 20, nullable: false })
|
||||
@Column({ type: 'varchar', length: 20, nullable: true })
|
||||
p11_3: string;
|
||||
|
||||
@Column({ type: 'varchar', length: 20, nullable: false })
|
||||
@Column({ type: 'varchar', length: 20, nullable: true })
|
||||
p11_4: string;
|
||||
|
||||
@Column({ type: 'varchar', length: 20, nullable: false })
|
||||
@Column({ type: 'varchar', length: 20, nullable: true })
|
||||
p12_A_1: string;
|
||||
|
||||
@Column({ type: 'varchar', length: 20, nullable: false })
|
||||
@Column({ type: 'varchar', length: 20, nullable: true })
|
||||
p12_A_2: string;
|
||||
|
||||
@Column({ type: 'varchar', length: 20, nullable: false })
|
||||
@Column({ type: 'varchar', length: 20, nullable: true })
|
||||
p12_A_3: string;
|
||||
|
||||
@Column({ type: 'varchar', length: 20, nullable: false })
|
||||
@Column({ type: 'varchar', length: 20, nullable: true })
|
||||
p12_A_4: string;
|
||||
|
||||
@Column({ type: 'varchar', length: 20, nullable: false })
|
||||
@Column({ type: 'varchar', length: 20, nullable: true })
|
||||
p12_B_1: string;
|
||||
|
||||
@Column({ type: 'varchar', length: 20, nullable: false })
|
||||
@Column({ type: 'varchar', length: 20, nullable: true })
|
||||
p12_B_2: string;
|
||||
|
||||
@Column({ type: 'varchar', length: 20, nullable: false })
|
||||
@Column({ type: 'varchar', length: 20, nullable: true })
|
||||
p12_B_3: string;
|
||||
|
||||
@Column({ type: 'varchar', length: 20, nullable: false })
|
||||
@Column({ type: 'varchar', length: 20, nullable: true })
|
||||
p12_B_4: string;
|
||||
|
||||
@Column({ type: 'varchar', length: 20, nullable: false })
|
||||
@Column({ type: 'varchar', length: 20, nullable: true })
|
||||
p12_C_1: string;
|
||||
|
||||
@Column({ type: 'varchar', length: 20, nullable: false })
|
||||
@Column({ type: 'varchar', length: 20, nullable: true })
|
||||
p12_C_2: string;
|
||||
|
||||
@Column({ type: 'varchar', length: 20, nullable: false })
|
||||
@Column({ type: 'varchar', length: 20, nullable: true })
|
||||
p12_C_3: string;
|
||||
|
||||
@Column({ type: 'varchar', length: 20, nullable: false })
|
||||
@Column({ type: 'varchar', length: 20, nullable: true })
|
||||
p12_C_4: string;
|
||||
|
||||
@Column({ type: 'varchar', length: 20, nullable: false })
|
||||
@Column({ type: 'varchar', length: 50, nullable: true })
|
||||
p12_D_1: string;
|
||||
|
||||
@Column({ type: 'varchar', length: 20, nullable: false })
|
||||
@Column({ type: 'varchar', length: 50, nullable: true })
|
||||
p12_D_2: string;
|
||||
|
||||
@Column({ type: 'varchar', length: 20, nullable: false })
|
||||
@Column({ type: 'varchar', length: 50, nullable: true })
|
||||
p12_D_3: string;
|
||||
|
||||
@Column({ type: 'varchar', length: 20, nullable: false })
|
||||
@Column({ type: 'varchar', length: 50, nullable: true })
|
||||
p12_D_4: string;
|
||||
|
||||
@Column({ type: 'varchar', length: 20, nullable: false })
|
||||
@Column({ type: 'varchar', length: 50, nullable: true })
|
||||
p12_D_5: string;
|
||||
|
||||
@Column({ type: 'varchar', length: 100, nullable: false })
|
||||
@Column({ type: 'varchar', length: 200, nullable: true })
|
||||
p13: string;
|
||||
|
||||
@Column({ type: 'varchar', length: 100, nullable: false })
|
||||
@Column({ type: 'varchar', length: 200, nullable: true })
|
||||
p14: string;
|
||||
|
||||
@Column({ type: 'varchar', length: 5, nullable: false })
|
||||
@Column({ type: 'varchar', length: 200, nullable: true })
|
||||
p15: string;
|
||||
|
||||
@Column({ type: 'varchar', length: 50, nullable: true })
|
||||
@Column({ type: 'varchar', length: 500, nullable: true })
|
||||
p16: string;
|
||||
|
||||
@Column({ type: 'varchar', length: 5, nullable: false })
|
||||
@Column({ type: 'varchar', length: 20, nullable: true })
|
||||
p17_1: string;
|
||||
|
||||
@Column({ type: 'varchar', length: 5, nullable: false })
|
||||
@Column({ type: 'varchar', length: 20, nullable: true })
|
||||
p17_2: string;
|
||||
|
||||
@Column({ type: 'varchar', length: 5, nullable: false })
|
||||
@Column({ type: 'varchar', length: 20, nullable: true })
|
||||
p17_3: string;
|
||||
|
||||
@Column({ type: 'varchar', length: 50, nullable: true })
|
||||
@Column({ type: 'varchar', length: 500, nullable: true })
|
||||
p18: string;
|
||||
|
||||
@OneToMany(()=>Servicio,(servicio)=>servicio.cuestionarioAlumno2)
|
||||
servicio:Servicio[];
|
||||
|
||||
@OneToMany(() => Servicio, (servicio) => servicio.cuestionarioAlumno2)
|
||||
servicio: Servicio[];
|
||||
}
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
import { Servicio } from "src/servicio/entities/servicio.entity";
|
||||
import { Column, Entity, OneToMany, PrimaryGeneratedColumn } from "typeorm";
|
||||
import { Servicio } from 'src/servicio/entities/servicio.entity';
|
||||
import {
|
||||
Column,
|
||||
CreateDateColumn,
|
||||
Entity,
|
||||
OneToMany,
|
||||
PrimaryGeneratedColumn,
|
||||
} from 'typeorm';
|
||||
|
||||
@Entity('cuestionario_programa')
|
||||
export class CuestionarioPrograma {
|
||||
@@ -30,6 +36,11 @@ export class CuestionarioPrograma {
|
||||
@Column({ type: 'varchar', length: 800, nullable: false })
|
||||
p7: string;
|
||||
|
||||
@OneToMany(()=>Servicio,(servicio)=>servicio.cuestionarioPrograma)
|
||||
servicio:Servicio[];
|
||||
@CreateDateColumn({ name: 'createdAt', type: 'datetime' })
|
||||
createdAt: Date;
|
||||
|
||||
// faltaba createdAT
|
||||
|
||||
@OneToMany(() => Servicio, (servicio) => servicio.cuestionarioPrograma)
|
||||
servicio: Servicio[];
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import { CuestionarioPrograma2 } from './entities/cuestionario-programa2.entity'
|
||||
import { Servicio } from 'src/servicio/entities/servicio.entity';
|
||||
import { ValidacionService } from 'src/helpers.services/validacion.service';
|
||||
import { ArchivoService } from 'src/helpers.services/archivo.service';
|
||||
import { ServicioService } from 'src/servicio/servicio.service';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
|
||||
@@ -9,6 +9,7 @@ import { ValidacionService } from 'src/helpers.services/validacion.service';
|
||||
import { Servicio } from 'src/servicio/entities/servicio.entity';
|
||||
import { messageByStatus } from 'src/messageByStatus';
|
||||
import { convertArrayToCSV } from 'convert-array-to-csv';
|
||||
import { ServicioService } from 'src/servicio/servicio.service';
|
||||
|
||||
@Injectable()
|
||||
export class CuestionarioPrograma2Service {
|
||||
@@ -21,7 +22,8 @@ export class CuestionarioPrograma2Service {
|
||||
private servicioRepository: Repository<Servicio>,
|
||||
private archivoService: ArchivoService,
|
||||
private validacionService: ValidacionService,
|
||||
) {}
|
||||
|
||||
) { }
|
||||
|
||||
async create(cuestionarioPrograma2: CreateCuestionarioPrograma2Dto) {
|
||||
let idServicio = cuestionarioPrograma2.idServicio;
|
||||
@@ -31,21 +33,30 @@ export class CuestionarioPrograma2Service {
|
||||
|
||||
let servicio = await this.servicioRepository.findOne({
|
||||
where: { idServicio },
|
||||
relations: ['cuestionarioPrograma2', 'status'],
|
||||
});
|
||||
if (!servicio) {
|
||||
throw new Error('No existe este Servicio Social.');
|
||||
throw new BadRequestException('No existe este Servicio Social.');
|
||||
}
|
||||
if (servicio.cuestionarioPrograma2.idCuestionarioPrograma2) {
|
||||
throw new Error(
|
||||
'Este Servicio Social ya cuenta con cuestionario de alumno',
|
||||
|
||||
if (servicio.cuestionarioPrograma2) {
|
||||
throw new BadRequestException(
|
||||
'Este Servicio Social ya cuenta con cuestionario de programa',
|
||||
);
|
||||
}
|
||||
|
||||
// Esta validacion esta incorrecta la cambie por la linea de arriva
|
||||
// if (servicio.cuestionarioPrograma2.idCuestionarioPrograma2) {
|
||||
// throw new BadRequestException(
|
||||
// 'Este Servicio Social ya cuenta con cuestionario de alumno',
|
||||
// );
|
||||
// }
|
||||
|
||||
console.log('el servicio social si existe', servicio);
|
||||
|
||||
console.log('antes de create ques2');
|
||||
if (messageByStatus.hasOwnProperty(servicio.status.idStatus))
|
||||
throw new Error(messageByStatus[servicio.status.idStatus]);
|
||||
throw new BadRequestException(messageByStatus[servicio.status.idStatus]);
|
||||
|
||||
console.log('despues de registrar cuestionario', cuestionario);
|
||||
|
||||
@@ -61,7 +72,7 @@ export class CuestionarioPrograma2Service {
|
||||
);
|
||||
|
||||
console.log(x);
|
||||
|
||||
await this.validacionService.validarPreTermino(idServicio)
|
||||
return respuestasRegistradas;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,142 +1,142 @@
|
||||
import {
|
||||
IsNotEmpty,
|
||||
IsNumber,
|
||||
IsOptional,
|
||||
IsString,
|
||||
Length,
|
||||
} from 'class-validator';
|
||||
|
||||
export class CreateCuestionarioPrograma2Dto {
|
||||
IsNotEmpty,
|
||||
IsNumber,
|
||||
IsOptional,
|
||||
IsString,
|
||||
Length,
|
||||
} from 'class-validator';
|
||||
|
||||
@IsNumber()
|
||||
@IsNotEmpty()
|
||||
idServicio:number
|
||||
export class CreateCuestionarioPrograma2Dto {
|
||||
|
||||
@IsNumber()
|
||||
@IsNotEmpty()
|
||||
idServicio: number
|
||||
|
||||
|
||||
// p1, p2, p4, p5, p6
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
@Length(1, 100)
|
||||
p1: string;
|
||||
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
@Length(1, 50)
|
||||
p2: string;
|
||||
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
@Length(1, 100)
|
||||
p4: string;
|
||||
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
@Length(1, 5)
|
||||
p5: string;
|
||||
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
@Length(1, 100)
|
||||
p6?: string;
|
||||
|
||||
// Sección p3_A
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
@Length(1, 50)
|
||||
p3_A_1: string;
|
||||
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
@Length(1, 50)
|
||||
p3_A_2: string;
|
||||
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
@Length(1, 50)
|
||||
p3_A_3: string;
|
||||
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
@Length(1, 50)
|
||||
p3_A_4: string;
|
||||
|
||||
// Sección p3_B
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
@Length(1, 50)
|
||||
p3_B_1: string;
|
||||
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
@Length(1, 50)
|
||||
p3_B_2: string;
|
||||
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
@Length(1, 50)
|
||||
p3_B_3: string;
|
||||
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
@Length(1, 50)
|
||||
p3_B_4: string;
|
||||
|
||||
// Sección p3_C
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
@Length(1, 50)
|
||||
p3_C_1: string;
|
||||
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
@Length(1, 50)
|
||||
p3_C_2: string;
|
||||
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
@Length(1, 50)
|
||||
p3_C_3: string;
|
||||
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
@Length(1, 50)
|
||||
p3_C_4: string;
|
||||
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
@Length(1, 50)
|
||||
p3_C_5: string;
|
||||
|
||||
// Sección p3_D
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
@Length(1, 50)
|
||||
p3_D_1: string;
|
||||
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
@Length(1, 50)
|
||||
p3_D_2: string;
|
||||
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
@Length(1, 50)
|
||||
p3_D_3: string;
|
||||
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
@Length(1, 50)
|
||||
p3_D_4: string;
|
||||
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
@Length(1, 50)
|
||||
p3_D_5: string;
|
||||
|
||||
// Sección p3_E
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
@Length(1, 50)
|
||||
p3_E_1: string;
|
||||
}
|
||||
|
||||
// p1, p2, p4, p5, p6
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
@Length(1, 500)
|
||||
p1: string;
|
||||
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
@Length(1, 200)
|
||||
p2: string;
|
||||
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
@Length(1, 500)
|
||||
p4: string;
|
||||
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
@Length(1, 200)
|
||||
p5: string;
|
||||
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
@Length(1, 500)
|
||||
p6?: string;
|
||||
|
||||
// Sección p3_A
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
@Length(1, 50)
|
||||
p3_A_1: string;
|
||||
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
@Length(1, 50)
|
||||
p3_A_2: string;
|
||||
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
@Length(1, 50)
|
||||
p3_A_3: string;
|
||||
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
@Length(1, 50)
|
||||
p3_A_4: string;
|
||||
|
||||
// Sección p3_B
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
@Length(1, 50)
|
||||
p3_B_1: string;
|
||||
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
@Length(1, 50)
|
||||
p3_B_2: string;
|
||||
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
@Length(1, 50)
|
||||
p3_B_3: string;
|
||||
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
@Length(1, 50)
|
||||
p3_B_4: string;
|
||||
|
||||
// Sección p3_C
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
@Length(1, 50)
|
||||
p3_C_1: string;
|
||||
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
@Length(1, 50)
|
||||
p3_C_2: string;
|
||||
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
@Length(1, 50)
|
||||
p3_C_3: string;
|
||||
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
@Length(1, 50)
|
||||
p3_C_4: string;
|
||||
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
@Length(1, 50)
|
||||
p3_C_5: string;
|
||||
|
||||
// Sección p3_D
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
@Length(1, 50)
|
||||
p3_D_1: string;
|
||||
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
@Length(1, 50)
|
||||
p3_D_2: string;
|
||||
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
@Length(1, 50)
|
||||
p3_D_3: string;
|
||||
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
@Length(1, 50)
|
||||
p3_D_4: string;
|
||||
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
@Length(1, 50)
|
||||
p3_D_5: string;
|
||||
|
||||
// Elimine esta tabla por que no existe en el cuestionario => Verificar si se ocupa en otro cuestionario ?
|
||||
// Sección p3_E
|
||||
// @IsString()
|
||||
// @IsNotEmpty()
|
||||
// @Length(1, 50)
|
||||
// p3_E_1: string;
|
||||
}
|
||||
|
||||
@@ -1,90 +1,95 @@
|
||||
import { Servicio } from "src/servicio/entities/servicio.entity";
|
||||
import { Column, Entity, OneToMany, PrimaryGeneratedColumn } from "typeorm";
|
||||
import { Servicio } from 'src/servicio/entities/servicio.entity';
|
||||
import {
|
||||
Column,
|
||||
CreateDateColumn,
|
||||
Entity,
|
||||
OneToMany,
|
||||
PrimaryGeneratedColumn,
|
||||
} from 'typeorm';
|
||||
|
||||
@Entity('cuestionario_programa_2')
|
||||
export class CuestionarioPrograma2 {
|
||||
@PrimaryGeneratedColumn()
|
||||
@PrimaryGeneratedColumn({ name: 'idCuestionarioPrograma2' })
|
||||
idCuestionarioPrograma2: number;
|
||||
|
||||
// Sección p3_A_*
|
||||
@Column({ type: 'varchar', length: 50, nullable: false })
|
||||
p3_A_1: string;
|
||||
@CreateDateColumn({ name: 'createdAt', type: 'datetime', nullable: true })
|
||||
createdAt?: Date;
|
||||
|
||||
@Column({ type: 'varchar', length: 50, nullable: false })
|
||||
p3_A_2: string;
|
||||
@Column({ name: 'p3_A_1', type: 'varchar', length: 50, nullable: true })
|
||||
p3_A_1?: string;
|
||||
|
||||
@Column({ type: 'varchar', length: 50, nullable: false })
|
||||
p3_A_3: string;
|
||||
@Column({ name: 'p3_A_2', type: 'varchar', length: 50, nullable: true })
|
||||
p3_A_2?: string;
|
||||
|
||||
@Column({ type: 'varchar', length: 50, nullable: false })
|
||||
p3_A_4: string;
|
||||
@Column({ name: 'p3_A_3', type: 'varchar', length: 50, nullable: true })
|
||||
p3_A_3?: string;
|
||||
|
||||
// Sección p3_B_*
|
||||
@Column({ type: 'varchar', length: 50, nullable: false })
|
||||
p3_B_1: string;
|
||||
@Column({ name: 'p3_A_4', type: 'varchar', length: 50, nullable: true })
|
||||
p3_A_4?: string;
|
||||
|
||||
@Column({ type: 'varchar', length: 50, nullable: false })
|
||||
p3_B_2: string;
|
||||
@Column({ name: 'p3_B_1', type: 'varchar', length: 50, nullable: true })
|
||||
p3_B_1?: string;
|
||||
|
||||
@Column({ type: 'varchar', length: 50, nullable: false })
|
||||
p3_B_3: string;
|
||||
@Column({ name: 'p3_B_2', type: 'varchar', length: 50, nullable: true })
|
||||
p3_B_2?: string;
|
||||
|
||||
@Column({ type: 'varchar', length: 50, nullable: false })
|
||||
p3_B_4: string;
|
||||
@Column({ name: 'p3_B_3', type: 'varchar', length: 50, nullable: true })
|
||||
p3_B_3?: string;
|
||||
|
||||
// Sección p3_C_*
|
||||
@Column({ type: 'varchar', length: 50, nullable: false })
|
||||
p3_C_1: string;
|
||||
@Column({ name: 'p3_B_4', type: 'varchar', length: 50, nullable: true })
|
||||
p3_B_4?: string;
|
||||
|
||||
@Column({ type: 'varchar', length: 50, nullable: false })
|
||||
p3_C_2: string;
|
||||
@Column({ name: 'p3_C_1', type: 'varchar', length: 50, nullable: true })
|
||||
p3_C_1?: string;
|
||||
|
||||
@Column({ type: 'varchar', length: 50, nullable: false })
|
||||
p3_C_3: string;
|
||||
@Column({ name: 'p3_C_2', type: 'varchar', length: 50, nullable: true })
|
||||
p3_C_2?: string;
|
||||
|
||||
@Column({ type: 'varchar', length: 50, nullable: false })
|
||||
p3_C_4: string;
|
||||
@Column({ name: 'p3_C_3', type: 'varchar', length: 50, nullable: true })
|
||||
p3_C_3?: string;
|
||||
|
||||
@Column({ type: 'varchar', length: 50, nullable: false })
|
||||
p3_C_5: string;
|
||||
@Column({ name: 'p3_C_4', type: 'varchar', length: 50, nullable: true })
|
||||
p3_C_4?: string;
|
||||
|
||||
// Sección p3_D_*
|
||||
@Column({ type: 'varchar', length: 50, nullable: false })
|
||||
p3_D_1: string;
|
||||
@Column({ name: 'p3_C_5', type: 'varchar', length: 50, nullable: true })
|
||||
p3_C_5?: string;
|
||||
|
||||
@Column({ type: 'varchar', length: 50, nullable: false })
|
||||
p3_D_2: string;
|
||||
@Column({ name: 'p3_D_1', type: 'varchar', length: 50, nullable: true })
|
||||
p3_D_1?: string;
|
||||
|
||||
@Column({ type: 'varchar', length: 50, nullable: false })
|
||||
p3_D_3: string;
|
||||
@Column({ name: 'p3_D_2', type: 'varchar', length: 50, nullable: true })
|
||||
p3_D_2?: string;
|
||||
|
||||
@Column({ type: 'varchar', length: 50, nullable: false })
|
||||
p3_D_4: string;
|
||||
@Column({ name: 'p3_D_3', type: 'varchar', length: 50, nullable: true })
|
||||
p3_D_3?: string;
|
||||
|
||||
@Column({ type: 'varchar', length: 50, nullable: false })
|
||||
p3_D_5: string;
|
||||
@Column({ name: 'p3_D_4', type: 'varchar', length: 50, nullable: true })
|
||||
p3_D_4?: string;
|
||||
|
||||
// Sección p3_E_*
|
||||
@Column({ type: 'varchar', length: 50, nullable: false })
|
||||
p3_E_1: string;
|
||||
@Column({ name: 'p3_D_5', type: 'varchar', length: 50, nullable: true })
|
||||
p3_D_5?: string;
|
||||
|
||||
// p1, p2, p4, p5, p6
|
||||
@Column({ type: 'varchar', length: 100, nullable: false })
|
||||
p1: string;
|
||||
@Column({ name: 'p3_E_1', type: 'varchar', length: 50, nullable: true })
|
||||
p3_E_1?: string;
|
||||
|
||||
@Column({ type: 'varchar', length: 50, nullable: false })
|
||||
p2: string;
|
||||
@Column({ name: 'p1', type: 'varchar', length: 500, nullable: true })
|
||||
p1?: string;
|
||||
|
||||
@Column({ type: 'varchar', length: 100, nullable: false })
|
||||
p4: string;
|
||||
@Column({ name: 'p2', type: 'varchar', length: 200, nullable: true })
|
||||
p2?: string;
|
||||
|
||||
@Column({ type: 'varchar', length: 5, nullable: false })
|
||||
p5: string;
|
||||
@Column({ name: 'p4', type: 'varchar', length: 500, nullable: true })
|
||||
p4?: string;
|
||||
|
||||
@Column({ type: 'varchar', length: 100, nullable: true })
|
||||
@Column({ name: 'p5', type: 'varchar', length: 200, nullable: true })
|
||||
p5?: string;
|
||||
|
||||
@Column({ name: 'p6', type: 'varchar', length: 500, nullable: true })
|
||||
p6?: string;
|
||||
|
||||
@OneToMany(()=>Servicio,(servicio)=>servicio.cuestionarioAlumno2)
|
||||
servicio:Servicio[];
|
||||
@Column({ name: 'p7', type: 'varchar', length: 200, nullable: true })
|
||||
p7?: string;
|
||||
|
||||
@OneToMany(() => Servicio, (servicio) => servicio.cuestionarioAlumno2)
|
||||
servicio: Servicio[];
|
||||
}
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
// src/drive/drive.controller.ts
|
||||
import {
|
||||
BadRequestException,
|
||||
Body,
|
||||
Controller,
|
||||
Delete,
|
||||
Get,
|
||||
Param,
|
||||
Post,
|
||||
Query,
|
||||
} from '@nestjs/common';
|
||||
import { DriveService } from './drive.service';
|
||||
import * as fs from 'fs';
|
||||
|
||||
@Controller('drive-test')
|
||||
export class DriveController {
|
||||
constructor(private readonly driveService: DriveService) { }
|
||||
|
||||
// ✅ Listar archivos/carpetas
|
||||
@Get('list')
|
||||
async list(@Query('pageToken') pageToken?: string) {
|
||||
return this.driveService.list(pageToken || '');
|
||||
}
|
||||
|
||||
// ✅ Crear carpeta dentro de CARPETA
|
||||
@Post('mkdir')
|
||||
async createFolder(@Body('name') name: string) {
|
||||
if (!name) {
|
||||
throw new BadRequestException('El nombre es obligatorio');
|
||||
}
|
||||
const folderId = await this.driveService.mkDir(name);
|
||||
return { folderId };
|
||||
}
|
||||
|
||||
// ✅ Obtener carpeta (buscar o crear)
|
||||
@Get('folder/:numeroCuenta')
|
||||
async getOrCreateFolder(
|
||||
@Param('numeroCuenta') numeroCuenta: string,
|
||||
) {
|
||||
const folderId = await this.driveService.folder(numeroCuenta);
|
||||
return { folderId };
|
||||
}
|
||||
|
||||
// ✅ Subir archivo (archivo dummy para pruebas)
|
||||
@Post('upload')
|
||||
async uploadFile(
|
||||
@Body('parent') parent: string,
|
||||
) {
|
||||
if (!parent) {
|
||||
throw new BadRequestException('Parent es obligatorio');
|
||||
}
|
||||
|
||||
// Archivo temporal para prueba
|
||||
const tempPath = './temp-test.txt';
|
||||
fs.writeFileSync(tempPath, 'Archivo de prueba DriveService');
|
||||
|
||||
const fileId = await this.driveService.uploadFile(
|
||||
tempPath,
|
||||
'test-drive.txt',
|
||||
'text/plain',
|
||||
parent,
|
||||
);
|
||||
|
||||
return { fileId };
|
||||
}
|
||||
|
||||
// ✅ Mover archivo (update)
|
||||
@Post('update')
|
||||
async updateFile(
|
||||
@Body('fileId') fileId: string,
|
||||
@Body('addParents') addParents: string,
|
||||
@Body('removeParents') removeParents: string,
|
||||
) {
|
||||
if (!fileId || !addParents || !removeParents) {
|
||||
throw new BadRequestException('Datos incompletos');
|
||||
}
|
||||
|
||||
return this.driveService.update(fileId, addParents, removeParents);
|
||||
}
|
||||
|
||||
// ✅ Eliminar archivo
|
||||
@Delete('delete/:fileId')
|
||||
async deleteFile(@Param('fileId') fileId: string) {
|
||||
await this.driveService.deleteFile(fileId);
|
||||
return { message: 'Archivo eliminado correctamente' };
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,10 @@
|
||||
// src/drive/drive.module.ts
|
||||
import { Module } from '@nestjs/common';
|
||||
import { DriveService } from './drive.service';
|
||||
import { DriveController } from './drive.controller';
|
||||
|
||||
@Module({
|
||||
controllers: [DriveController],
|
||||
providers: [DriveService],
|
||||
exports: [DriveService],
|
||||
})
|
||||
export class DriveModule {}
|
||||
export class DriveModule { }
|
||||
|
||||
+76
-55
@@ -1,9 +1,11 @@
|
||||
// src/drive/drive.service.ts
|
||||
import { Injectable, InternalServerErrorException } from '@nestjs/common';
|
||||
import {
|
||||
BadRequestException,
|
||||
Injectable,
|
||||
InternalServerErrorException,
|
||||
} from '@nestjs/common';
|
||||
import { google } from 'googleapis';
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import { error } from 'console';
|
||||
|
||||
@Injectable()
|
||||
export class DriveService {
|
||||
@@ -11,30 +13,32 @@ export class DriveService {
|
||||
|
||||
private loadCredentials() {
|
||||
try {
|
||||
const credenciales = JSON.parse(
|
||||
fs.readFileSync(path.resolve('./cred.json'), 'utf8'),
|
||||
const oAuth2Client = new google.auth.OAuth2(
|
||||
process.env.CLIENT_ID,
|
||||
process.env.CLIENT_SECRET,
|
||||
);
|
||||
credenciales.private_key = credenciales.private_key.replace(/\\n/g, '\n');
|
||||
return new google.auth.JWT({
|
||||
email: credenciales.client_email,
|
||||
key: credenciales.private_key,
|
||||
scopes: ['https://www.googleapis.com/auth/drive'],
|
||||
});
|
||||
|
||||
oAuth2Client.setCredentials({
|
||||
refresh_token: process.env.REFRESH_TOKEN,
|
||||
});
|
||||
|
||||
return oAuth2Client;
|
||||
} catch (err) {
|
||||
console.error('❌ Error cargando credenciales:', err);
|
||||
throw new InternalServerErrorException('Error al cargar credenciales');
|
||||
throw new InternalServerErrorException(
|
||||
'Error al cargar credenciales de Google Drive',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
async list(pageToken = '') {
|
||||
const authClient = await this.loadCredentials();
|
||||
const authClient = this.loadCredentials();
|
||||
const drive = google.drive({ version: 'v3', auth: authClient });
|
||||
|
||||
try {
|
||||
const res = await drive.files.list({
|
||||
corpora: 'user',
|
||||
supportsTeamDrives: true,
|
||||
includeTeamDriveItems: true,
|
||||
supportsAllDrives: true,
|
||||
includeItemsFromAllDrives: true,
|
||||
spaces: 'drive',
|
||||
pageSize: 1000,
|
||||
pageToken,
|
||||
@@ -50,28 +54,36 @@ export class DriveService {
|
||||
|
||||
async deleteFile(fileId: string) {
|
||||
if (fileId === process.env.CARPETA) {
|
||||
throw new Error('No se puede eliminar este archivo/carpeta.');
|
||||
throw new BadRequestException(
|
||||
'No se puede eliminar este archivo/carpeta.',
|
||||
);
|
||||
}
|
||||
const authClient = await this.loadCredentials();
|
||||
console.log('Eliminando archivo de Drive, ID:', fileId);
|
||||
const authClient = this.loadCredentials();
|
||||
const drive = google.drive({ version: 'v3', auth: authClient });
|
||||
|
||||
try {
|
||||
return await drive.files.delete({ fileId });
|
||||
} catch (err) {
|
||||
throw new InternalServerErrorException(
|
||||
'Error al eliminar archivo: ' + err.message,
|
||||
);
|
||||
console.error('Error al eliminar archivo de Drive:', err.message);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
async uploadFile(filePath: string, name: string, mimeType: string, parent: string) {
|
||||
const authClient = await this.loadCredentials();
|
||||
async uploadFile(
|
||||
filePath: string,
|
||||
name: string,
|
||||
mimeType: string,
|
||||
parent: string,
|
||||
) {
|
||||
const authClient = this.loadCredentials();
|
||||
const drive = google.drive({ version: 'v3', auth: authClient });
|
||||
|
||||
const requestBody = {
|
||||
name,
|
||||
parents: [parent],
|
||||
};
|
||||
|
||||
const media = {
|
||||
mimeType,
|
||||
body: fs.createReadStream(filePath),
|
||||
@@ -82,9 +94,12 @@ export class DriveService {
|
||||
requestBody,
|
||||
media,
|
||||
fields: 'id',
|
||||
supportsAllDrives: true,
|
||||
});
|
||||
|
||||
fs.unlinkSync(filePath);
|
||||
return res.data.id;
|
||||
console.log('Archivo subido a Drive, ID:', res.data.id);
|
||||
return res.data.id!;
|
||||
} catch (err) {
|
||||
throw new InternalServerErrorException(
|
||||
'Error al subir archivo: ' + err.message,
|
||||
@@ -93,36 +108,35 @@ export class DriveService {
|
||||
}
|
||||
|
||||
async mkDir(name: string): Promise<string> {
|
||||
const authClient = await this.loadCredentials();
|
||||
if (!name) {
|
||||
throw new BadRequestException('Nombre de carpeta inválido');
|
||||
}
|
||||
|
||||
if (!process.env.CARPETA) {
|
||||
throw new InternalServerErrorException('CARPETA no configurada');
|
||||
}
|
||||
|
||||
const authClient = this.loadCredentials();
|
||||
const drive = google.drive({ version: 'v3', auth: authClient });
|
||||
|
||||
|
||||
if(!name){
|
||||
throw new Error()
|
||||
}
|
||||
if(!process.env.CARPETA){
|
||||
throw new Error()
|
||||
}
|
||||
|
||||
const requestBody = {
|
||||
name,
|
||||
mimeType: 'application/vnd.google-apps.folder',
|
||||
parents: [process.env.CARPETA],
|
||||
};
|
||||
|
||||
|
||||
try {
|
||||
const res = await drive.files.create({
|
||||
requestBody,
|
||||
fields: 'id',
|
||||
supportsAllDrives: true,
|
||||
});
|
||||
|
||||
if(!res.data.id){
|
||||
throw new Error()
|
||||
}
|
||||
if (!res.data.id) {
|
||||
throw new BadRequestException('No se pudo crear la carpeta');
|
||||
}
|
||||
|
||||
return res.data.id;
|
||||
|
||||
} catch (err) {
|
||||
throw new InternalServerErrorException(
|
||||
'Error al crear carpeta: ' + err.message,
|
||||
@@ -131,7 +145,7 @@ export class DriveService {
|
||||
}
|
||||
|
||||
async update(fileId: string, addParents: string, removeParents: string) {
|
||||
const authClient = await this.loadCredentials();
|
||||
const authClient = this.loadCredentials();
|
||||
const drive = google.drive({ version: 'v3', auth: authClient });
|
||||
|
||||
try {
|
||||
@@ -139,6 +153,7 @@ export class DriveService {
|
||||
fileId,
|
||||
addParents,
|
||||
removeParents,
|
||||
supportsAllDrives: true,
|
||||
});
|
||||
return res.data;
|
||||
} catch (err) {
|
||||
@@ -148,24 +163,30 @@ export class DriveService {
|
||||
}
|
||||
}
|
||||
|
||||
async folder(numeroCuenta: string) {
|
||||
let pageToken = '';
|
||||
do {
|
||||
const res = await this.list(pageToken);
|
||||
if(!res.files){
|
||||
throw new Error()
|
||||
async folder(numeroCuenta: string): Promise<string> {
|
||||
if (!process.env.CARPETA) {
|
||||
throw new InternalServerErrorException('CARPETA no configurada');
|
||||
}
|
||||
|
||||
const authClient = this.loadCredentials();
|
||||
const drive = google.drive({ version: 'v3', auth: authClient });
|
||||
|
||||
const res = await drive.files.list({
|
||||
q: `
|
||||
mimeType='application/vnd.google-apps.folder'
|
||||
and name='${numeroCuenta}'
|
||||
and '${process.env.CARPETA}' in parents
|
||||
and trashed=false
|
||||
`,
|
||||
fields: 'files(id, name)',
|
||||
supportsAllDrives: true,
|
||||
includeItemsFromAllDrives: true,
|
||||
});
|
||||
|
||||
if (res.data.files?.length) {
|
||||
return res.data.files[0].id!;
|
||||
}
|
||||
for (const file of res.files) {
|
||||
if (
|
||||
file.name === numeroCuenta &&
|
||||
file.mimeType === 'application/vnd.google-apps.folder'
|
||||
) {
|
||||
return file.id;
|
||||
}
|
||||
}
|
||||
pageToken = res.nextPageToken || '';
|
||||
|
||||
} while (pageToken);
|
||||
return this.mkDir(numeroCuenta);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,19 @@ const preRegistro = (password, nombre) => {
|
||||
subject: 'Notificación de Pre-Registro.',
|
||||
msj: `Estimado(a) ${nombre}:
|
||||
|
||||
Te informamos que la dependencia en donde decidiste realizar tu servicio social ya te registró en nuestro sistema de servicio social, por lo que para completar el proceso debes ingresar en un periodo máximo de 10 días hábiles a partir de la recepción de este mensaje, a la página https://iris.acatlan.unam.mx/ con tu número de cuenta y contraseña: ${password}, para llenar un formulario con tus datos.
|
||||
|
||||
Te informamos que la dependencia en donde decidiste realizar tu servicio social
|
||||
ya te registró en nuestro sistema de servicio social, por lo que para completar
|
||||
el proceso deberás:
|
||||
|
||||
|
||||
-Ingresar en un periodo máximo de 10 días hábiles a partir de la recepción de este mensaje,
|
||||
a la página https://iris.acatlan.unam.mx/
|
||||
-Tu usuario será tu número de cuenta
|
||||
-Tu contraseña es: ${password}
|
||||
-Deberás llenar un formulario con tus datos
|
||||
|
||||
|
||||
|
||||
En caso de no realizar dicho registro, tu trámite queda inconcluso y no nos hacemos responsables por las horas de servicio social prestadas en cualquier dependencia.
|
||||
|
||||
@@ -272,6 +284,7 @@ ${atentamente}
|
||||
};
|
||||
};
|
||||
|
||||
// Quitamos el module para que podamos exportar normal anteriormente module.export
|
||||
module.exports = {
|
||||
preRegistro,
|
||||
preRegistroRechazadoAlumno,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Injectable } from "@nestjs/common";
|
||||
import { BadRequestException, Injectable } from "@nestjs/common";
|
||||
import { InjectRepository } from "@nestjs/typeorm";
|
||||
import moment from "moment";
|
||||
import { Servicio } from "src/servicio/entities/servicio.entity";
|
||||
@@ -8,49 +8,49 @@ import validator from "validator";
|
||||
|
||||
@Injectable()
|
||||
export class ValidacionService {
|
||||
constructor(
|
||||
@InjectRepository(Servicio)
|
||||
private servicioRepository:Repository<Servicio>,
|
||||
){}
|
||||
constructor(
|
||||
@InjectRepository(Servicio)
|
||||
private servicioRepository: Repository<Servicio>,
|
||||
) { }
|
||||
|
||||
caracterEspecial(char) {
|
||||
caracterEspecial(char) {
|
||||
const charset = [' ', '.', ',', ':', ';', '?', '¿', '!', '¡', '(', ')', '"', "'", '-', '_', '/', '#', '%', '\n'];
|
||||
return charset.includes(char);
|
||||
}
|
||||
|
||||
yaExiste(campo, m) {
|
||||
throw new Error(`Ya se encuentra en uso ${m ? 'el' : 'la'} ${campo}.`);
|
||||
yaExiste(campo, m) {
|
||||
throw new BadRequestException(`Ya se encuentra en uso ${m ? 'el' : 'la'} ${campo}.`);
|
||||
}
|
||||
|
||||
noValido(campo, m, razon) {
|
||||
throw new Error(`${m ? 'El' : 'La'} ${campo} no es valid${m ? 'o' : 'a'}, ${razon}.`);
|
||||
noValido(campo, m, razon) {
|
||||
throw new BadRequestException(`${m ? 'El' : 'La'} ${campo} no es valid${m ? 'o' : 'a'}, ${razon}.`);
|
||||
}
|
||||
|
||||
noHay(variable, campo, m) {
|
||||
if (!variable) throw new Error(`No se mando ${m ? 'el' : 'la'} ${campo}.`);
|
||||
noHay(variable, campo, m) {
|
||||
if (!variable) throw new BadRequestException(`No se mando ${m ? 'el' : 'la'} ${campo}.`);
|
||||
}
|
||||
|
||||
validacionBasicaStr(texto, campo, m, length) {
|
||||
validacionBasicaStr(texto, campo, m, length) {
|
||||
this.noHay(texto, campo, m);
|
||||
if (typeof texto !== 'string') this.noValido(campo, m, 'no se mando una string');
|
||||
if (length && texto.length > length) this.noValido(campo, m, 'tiene más caracteres de lo permitido');
|
||||
return texto;
|
||||
}
|
||||
|
||||
validarNumeroEntero(numero, campo, m: boolean = true) {
|
||||
validarNumeroEntero(numero, campo, m: boolean = true) {
|
||||
this.noHay(numero, campo, m);
|
||||
if (typeof numero === 'number') numero = numero.toString();
|
||||
if (!validator.isNumeric(numero, { no_symbols: true })) this.noValido(campo, m, 'no es un número entero válido');
|
||||
return Number(numero);
|
||||
}
|
||||
|
||||
validarCorreo(correo: any, length?: any, campo: string = 'correo', m: boolean = true) {
|
||||
validarCorreo(correo: any, length?: any, campo: string = 'correo', m: boolean = true) {
|
||||
this.validacionBasicaStr(correo, campo, m, length);
|
||||
if (!validator.isEmail(correo)) this.noValido(campo, m, 'no es un correo válido');
|
||||
return correo;
|
||||
}
|
||||
|
||||
validarTexto(texto, campo, m, length) {
|
||||
validarTexto(texto, campo, m, length) {
|
||||
this.validacionBasicaStr(texto, campo, m, length);
|
||||
for (const char of texto) {
|
||||
if (!validator.isAlpha(char, 'es-ES') && char !== ' ' && char !== '.') {
|
||||
@@ -60,7 +60,7 @@ export class ValidacionService {
|
||||
return texto;
|
||||
}
|
||||
|
||||
validarAlfanumerico(texto, campo, m, length) {
|
||||
validarAlfanumerico(texto, campo, m, length) {
|
||||
this.validacionBasicaStr(texto, campo, m, length);
|
||||
for (const char of texto) {
|
||||
if (!this.caracterEspecial(char) && !validator.isAlphanumeric(char, 'es-ES')) {
|
||||
@@ -70,7 +70,7 @@ export class ValidacionService {
|
||||
return texto;
|
||||
}
|
||||
|
||||
validarNumeroCuenta(numeroCuenta, campo = 'numero de cuenta', m = true) {
|
||||
validarNumeroCuenta(numeroCuenta, campo = 'numero de cuenta', m = true) {
|
||||
this.validacionBasicaStr(numeroCuenta, campo, m, 9);
|
||||
if (!validator.isNumeric(numeroCuenta, { no_symbols: true })) {
|
||||
this.noValido(campo, m, 'tiene caracteres que no son números');
|
||||
@@ -78,14 +78,14 @@ export class ValidacionService {
|
||||
return numeroCuenta;
|
||||
}
|
||||
|
||||
validarFecha(fecha, campo, m) {
|
||||
validarFecha(fecha, campo, m) {
|
||||
const fechaMoment = moment(fecha);
|
||||
this.noHay(fecha, campo, m);
|
||||
if (!fechaMoment.isValid()) this.noValido(campo, m, 'no es una fecha válida');
|
||||
return fechaMoment;
|
||||
}
|
||||
|
||||
validarNumero(numero, campo, m, length, no_symbols = true, makeNumber = false) {
|
||||
validarNumero(numero, campo, m, length, no_symbols = true, makeNumber = false) {
|
||||
this.validacionBasicaStr(numero, campo, m, length);
|
||||
if (!validator.isNumeric(numero, { no_symbols })) {
|
||||
this.noValido(campo, m, 'tiene caracteres que no son números');
|
||||
@@ -93,32 +93,53 @@ export class ValidacionService {
|
||||
return makeNumber ? Number(numero) : numero;
|
||||
}
|
||||
|
||||
validarObjetoVacio(obj) {
|
||||
validarObjetoVacio(obj) {
|
||||
return Object.keys(obj).length === 0;
|
||||
}
|
||||
|
||||
async validarPreTermino(idServicio) {
|
||||
const res = await this.servicioRepository.findOne({ where: { idServicio } });
|
||||
async validarPreTermino(idServicio: number) {
|
||||
const res = await this.servicioRepository.findOne({
|
||||
where: { idServicio },
|
||||
relations: [
|
||||
'cuestionarioPrograma',
|
||||
'cuestionarioPrograma2',
|
||||
'cuestionarioAlumno',
|
||||
'cuestionarioAlumno2',
|
||||
],
|
||||
});
|
||||
|
||||
if (!res) return '';
|
||||
|
||||
const tieneCuestionarioPrograma =
|
||||
!!res.cuestionarioPrograma?.idCuestionarioPrograma ||
|
||||
!!res.cuestionarioPrograma2?.idCuestionarioPrograma2;
|
||||
|
||||
const tieneCuestionarioAlumno =
|
||||
!!res.cuestionarioAlumno?.idCuestionarioAlumno ||
|
||||
!!res.cuestionarioAlumno2?.idCuestionarioAlumno2;
|
||||
|
||||
const tieneDocumentos =
|
||||
!!res.cartaTermino && !!res.informeGlobal;
|
||||
|
||||
if (tieneCuestionarioPrograma && tieneCuestionarioAlumno && tieneDocumentos) {
|
||||
await this.servicioRepository.update(idServicio, {
|
||||
status: { idStatus: 5 },
|
||||
});
|
||||
|
||||
if (
|
||||
(res?.cuestionarioPrograma.idCuestionarioPrograma || res?.cuestionarioPrograma2.idCuestionarioPrograma2) &&
|
||||
(res.cuestionarioAlumno.idCuestionarioAlumno || res.cuestionarioAlumno2.idCuestionarioAlumno2) &&
|
||||
res.cartaTermino &&
|
||||
res.informeGlobal
|
||||
) {
|
||||
await this.servicioRepository.update({ idServicio }, { status: {idStatus:5} });
|
||||
return 'Este Servicio Social pasó a Término, espera a que COESI autorice tu liberación.';
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
validarCuestionarioAlumno2(body) {
|
||||
|
||||
validarCuestionarioAlumno2(body) {
|
||||
const optionalKeys = ['p5', 'p8', 'p16', 'p18'];
|
||||
if (Array.isArray(body.p1)) body.p1 = body.p1.join(', ');
|
||||
|
||||
for (const [key, value] of Object.entries(body)) {
|
||||
if (!optionalKeys.includes(key) && (value === null || value === undefined || value === '')) {
|
||||
throw new Error(`El campo ${key} no puede estar vacío.`);
|
||||
throw new BadRequestException(`El campo ${key} no puede estar vacío.`);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -136,20 +157,20 @@ export class ValidacionService {
|
||||
|
||||
for (const key of expectedKeys) {
|
||||
if (!(key in body)) {
|
||||
throw new Error(`Falta la respuesta para la pregunta ${key}.`);
|
||||
throw new BadRequestException(`Falta la respuesta para la pregunta ${key}.`);
|
||||
}
|
||||
}
|
||||
|
||||
return body;
|
||||
}
|
||||
|
||||
validarCuestionarioPrograma2(body) {
|
||||
validarCuestionarioPrograma2(body) {
|
||||
const camposOpcionales = ['p6'];
|
||||
if (Array.isArray(body.p1)) body.p1 = body.p1.join(', ');
|
||||
|
||||
for (const [key, value] of Object.entries(body)) {
|
||||
if (!camposOpcionales.includes(key) && (value === null || value === undefined || value === '')) {
|
||||
throw new Error(`El campo ${key} no puede estar vacío.`);
|
||||
throw new BadRequestException(`El campo ${key} no puede estar vacío.`);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -163,10 +184,10 @@ export class ValidacionService {
|
||||
|
||||
for (const key of expectedKeys) {
|
||||
if (!(key in body)) {
|
||||
throw new Error(`Falta la respuesta para la pregunta ${key}.`);
|
||||
throw new BadRequestException(`Falta la respuesta para la pregunta ${key}.`);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return body;
|
||||
}
|
||||
}
|
||||
+13
-2
@@ -1,12 +1,23 @@
|
||||
import { NestFactory } from '@nestjs/core';
|
||||
import { AppModule } from './app.module';
|
||||
import { ValidationPipe } from '@nestjs/common';
|
||||
|
||||
async function bootstrap() {
|
||||
const app = await NestFactory.create(AppModule);
|
||||
|
||||
app.useGlobalPipes(
|
||||
new ValidationPipe({
|
||||
whitelist: true, // elimina propiedades que no existan en el DTO
|
||||
transform: true, // permite que @Type() funcione
|
||||
transformOptions: { enableImplicitConversion: true }, // convierte strings → number/date
|
||||
}),
|
||||
);
|
||||
|
||||
|
||||
app.enableCors();
|
||||
await app.listen(process.env.PORT ?? 3000);
|
||||
console.log(`Aplicación corriendo en: http://localhost:${process.env.PORT ?? 3000}`);
|
||||
await app.listen(process.env.APP_PORT ?? 3000);
|
||||
console.log(
|
||||
`Aplicación corriendo en: http://localhost:${process.env.APP_PORT ?? 3000}`,
|
||||
);
|
||||
}
|
||||
bootstrap();
|
||||
|
||||
@@ -1,6 +1,13 @@
|
||||
import { Servicio } from "src/servicio/entities/servicio.entity";
|
||||
import { Usuario } from "src/usuario/entities/usuario.entity";
|
||||
import { Column, Entity, ManyToOne, OneToMany, PrimaryGeneratedColumn } from "typeorm";
|
||||
import { Servicio } from 'src/servicio/entities/servicio.entity';
|
||||
import { Usuario } from 'src/usuario/entities/usuario.entity';
|
||||
import {
|
||||
Column,
|
||||
Entity,
|
||||
JoinColumn,
|
||||
ManyToOne,
|
||||
OneToMany,
|
||||
PrimaryGeneratedColumn,
|
||||
} from 'typeorm';
|
||||
|
||||
@Entity('programa')
|
||||
export class Programa {
|
||||
@@ -25,9 +32,10 @@ export class Programa {
|
||||
@Column({ type: 'boolean', default: true })
|
||||
activo: boolean;
|
||||
|
||||
@ManyToOne(()=>Usuario,(usuario)=>usuario.programa)
|
||||
usuario:Usuario;
|
||||
@ManyToOne(() => Usuario, (usuario) => usuario.programa)
|
||||
@JoinColumn({ name: 'idUsuario' })
|
||||
usuario: Usuario;
|
||||
|
||||
@OneToMany(()=>Servicio,(servicio)=>servicio.cuestionarioAlumno2)
|
||||
servicio:Servicio[];
|
||||
@OneToMany(() => Servicio, (servicio) => servicio.cuestionarioAlumno2)
|
||||
servicio: Servicio[];
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ import {
|
||||
UseInterceptors,
|
||||
BadRequestException,
|
||||
Param,
|
||||
ParseIntPipe,
|
||||
} from '@nestjs/common';
|
||||
import { FileInterceptor } from '@nestjs/platform-express';
|
||||
import { diskStorage } from 'multer';
|
||||
@@ -70,13 +71,18 @@ export class ProgramaController {
|
||||
@UseGuards(AuthGuard('jwt'))
|
||||
async reasignarProgramas(
|
||||
@Body() email: Email,
|
||||
@Param('idUsuario') idUsuario: number,
|
||||
@Param('idUsuario', ParseIntPipe) idUsuario: number,
|
||||
) {
|
||||
|
||||
console.log('BODY:', email);
|
||||
console.log('PARAM:', idUsuario);
|
||||
|
||||
try {
|
||||
const data = await this.programaService.reasignarProgramas(
|
||||
idUsuario,
|
||||
email.correo,
|
||||
);
|
||||
|
||||
return {
|
||||
statusCode: 200,
|
||||
message: 'Programas reasignados con éxito',
|
||||
|
||||
@@ -1,9 +1,27 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { ProgramaService } from './programa.service';
|
||||
import { ProgramaController } from './programa.controller';
|
||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
import { Programa } from './entities/programa.entity';
|
||||
import { Usuario } from 'src/usuario/entities/usuario.entity';
|
||||
import { UsuarioModule } from 'src/usuario/usuario.module';
|
||||
import { ValidacionService } from 'src/helpers.services/validacion.service';
|
||||
import { AuthService } from 'src/auth/auth.service';
|
||||
import { gmail } from 'src/helpers.services/gmail.service';
|
||||
import { AuthModule } from 'src/auth/auth.module';
|
||||
import { JwtService } from '@nestjs/jwt';
|
||||
import { Servicio } from 'src/servicio/entities/servicio.entity';
|
||||
|
||||
@Module({
|
||||
imports: [TypeOrmModule.forFeature([Programa, Servicio]), UsuarioModule],
|
||||
controllers: [ProgramaController],
|
||||
providers: [ProgramaService],
|
||||
providers: [
|
||||
ProgramaService,
|
||||
AuthService,
|
||||
ValidacionService,
|
||||
gmail,
|
||||
JwtService,
|
||||
],
|
||||
exports: [TypeOrmModule],
|
||||
})
|
||||
export class ProgramaModule {}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { BadRequestException, Injectable } from '@nestjs/common';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
import { Repository } from 'typeorm';
|
||||
import { Like, Repository } from 'typeorm';
|
||||
import * as csv from 'csvtojson';
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
@@ -13,6 +13,8 @@ import { ValidacionService } from 'src/helpers.services/validacion.service';
|
||||
import { AuthService } from 'src/auth/auth.service';
|
||||
import { gmail } from 'src/helpers.services/gmail.service';
|
||||
import { SendMailDto } from 'src/helpers.services/dto/send-email.dto';
|
||||
const { enviarSec } = require('../helpers.services/msjCorreos');
|
||||
|
||||
|
||||
@Injectable()
|
||||
export class ProgramaService {
|
||||
@@ -24,7 +26,7 @@ export class ProgramaService {
|
||||
private validacionService: ValidacionService,
|
||||
private authService: AuthService,
|
||||
private gmail: gmail,
|
||||
) {}
|
||||
) { }
|
||||
|
||||
async cargaMasiva(nombreArchivo: string): Promise<{ message: string }> {
|
||||
const filePath = path.join('server/uploads', nombreArchivo);
|
||||
@@ -50,12 +52,14 @@ export class ProgramaService {
|
||||
|
||||
try {
|
||||
this.validacionService.validarCorreo(prog.correo);
|
||||
} catch {
|
||||
} catch (err) {
|
||||
console.log(err)
|
||||
mensaje += 'Correo inválido. Línea omitida.\n\n';
|
||||
continue;
|
||||
}
|
||||
|
||||
const acatlan = prog.clave.substr(4, 7) === '-12/20-';
|
||||
const acatlan = prog.clave.substr(4, 8) === '-12/145-';
|
||||
console.log("clave:", prog.clave.substr(4, 8))
|
||||
const activo = Number(prog.clave.substr(0, 4)) === today.year();
|
||||
|
||||
let responsable = await this.usuarioRepo.findOne({
|
||||
@@ -67,11 +71,18 @@ export class ProgramaService {
|
||||
},
|
||||
});
|
||||
|
||||
//Agregamos esta linea para verificar los logs
|
||||
console.log("prog:", prog);
|
||||
|
||||
|
||||
if (!responsable) {
|
||||
const password = await this.authService.encriptar(
|
||||
this.authService.generarPassword(),
|
||||
);
|
||||
const correoInfo = enviarSec(password, prog.correo, prog.nombre);
|
||||
|
||||
let contraseña = await this.authService.generarPassword();
|
||||
const password = await this.authService.encriptar(contraseña);
|
||||
|
||||
|
||||
|
||||
const correoInfo = enviarSec(contraseña, prog.correo, prog.nombre);
|
||||
|
||||
responsable = await this.usuarioRepo.create({
|
||||
usuario: prog.correo,
|
||||
@@ -92,10 +103,6 @@ export class ProgramaService {
|
||||
fecha_recibido: new Date(),
|
||||
};
|
||||
|
||||
if (!process.env.TOKEN_GMAIL) {
|
||||
throw new Error('No existe el token');
|
||||
}
|
||||
|
||||
try {
|
||||
responsable = await this.usuarioRepo.save(responsable);
|
||||
|
||||
@@ -167,6 +174,15 @@ export class ProgramaService {
|
||||
mensaje += `Error creando programa: ${err.message}\n`;
|
||||
}
|
||||
} else {
|
||||
await this.programaRepo.update(
|
||||
{ idPrograma: existente.idPrograma },
|
||||
{ institucion: prog.institucion, programa: prog.programa }
|
||||
)
|
||||
|
||||
await this.usuarioRepo.update(
|
||||
{ idUsuario: responsable.idUsuario },
|
||||
{ nombre: prog.nombre }
|
||||
)
|
||||
mensaje += `Programa ACATLÁN ya pertenece a ${responsable.usuario}\n`;
|
||||
}
|
||||
}
|
||||
@@ -189,17 +205,22 @@ export class ProgramaService {
|
||||
|
||||
const usuario = await this.usuarioRepo.findOne({
|
||||
where: { idUsuario },
|
||||
relations: ['tipoUsuario'],
|
||||
});
|
||||
|
||||
if (!usuario) {
|
||||
throw new Error('No existe este usuario.');
|
||||
throw new BadRequestException('No existe este usuario.');
|
||||
}
|
||||
|
||||
if (usuario.tipoUsuario.idTipoUsuario !== 2) {
|
||||
throw new Error('No es un usuario de tipo responsable');
|
||||
throw new BadRequestException('No es un usuario de tipo responsable');
|
||||
}
|
||||
return this.programaRepo.find({
|
||||
where: { usuario: { idUsuario } },
|
||||
const year = new Date().getFullYear().toString();
|
||||
|
||||
return await this.programaRepo.find({
|
||||
where: {
|
||||
usuario: { idUsuario }, clavePrograma: Like(`${year}%`),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
@@ -211,20 +232,23 @@ export class ProgramaService {
|
||||
|
||||
const usuario = await this.usuarioRepo.findOne({
|
||||
where: { idUsuario },
|
||||
relations: ['tipoUsuario'], // Se agrego la relacion con tipo de usuario
|
||||
});
|
||||
|
||||
if (!usuario) {
|
||||
throw new Error('No existe este usuario.');
|
||||
throw new BadRequestException('No existe este usuario.');
|
||||
}
|
||||
|
||||
if (usuario.tipoUsuario.idTipoUsuario !== 2) {
|
||||
throw new Error('No es un usuario de tipo responsable');
|
||||
throw new BadRequestException('No es un usuario de tipo responsable');
|
||||
}
|
||||
const year = new Date().getFullYear().toString();
|
||||
|
||||
return this.programaRepo.find({
|
||||
return await this.programaRepo.find({
|
||||
where: {
|
||||
usuario: { idUsuario },
|
||||
activo: true,
|
||||
clavePrograma: Like(`${year}%`)
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -240,19 +264,20 @@ export class ProgramaService {
|
||||
|
||||
let usuarioNuevo = await this.usuarioRepo.findOne({
|
||||
where: { idUsuario: idusuario },
|
||||
relations: ["tipoUsuario"],
|
||||
});
|
||||
|
||||
if (!usuarioNuevo) throw new Error('No existe este usuario.');
|
||||
if (!usuarioNuevo) throw new BadRequestException('No existe este usuario.');
|
||||
if (usuarioNuevo.tipoUsuario.idTipoUsuario != 2)
|
||||
throw new Error('No es un usuario de tipo responsable');
|
||||
throw new BadRequestException('No es un usuario de tipo responsable');
|
||||
if (usuarioNuevo.usuario === correoOtroResponsable)
|
||||
throw new Error('Son el mismo usuario.');
|
||||
throw new BadRequestException('Son el mismo usuario.');
|
||||
|
||||
let viejoResponsable = await this.usuarioRepo.findOne({
|
||||
where: { usuario: otroResponsable },
|
||||
});
|
||||
|
||||
if (!viejoResponsable) throw new Error('No existe este usuario.');
|
||||
if (!viejoResponsable) throw new BadRequestException('No existe este usuario.');
|
||||
|
||||
await this.programaRepo.update(
|
||||
{ usuario: viejoResponsable },
|
||||
|
||||
@@ -26,11 +26,11 @@ export class CrearServicioDto {
|
||||
@IsEmail()
|
||||
correo: string;
|
||||
|
||||
@IsDate()
|
||||
fechaInicio: Date;
|
||||
@IsDateString()
|
||||
fechaInicio: string; // Cambiado a string antes tenia Date
|
||||
|
||||
@IsDate()
|
||||
fechaFin: Date;
|
||||
@IsDateString()
|
||||
fechaFin: string; // Cambiado a string antes tenia Date
|
||||
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
|
||||
@@ -12,7 +12,7 @@ export class RegistroValidadoDto {
|
||||
idServicio: number;
|
||||
|
||||
@IsOptional()
|
||||
fechaNacimiento?: Date;
|
||||
fechaNacimiento?: string; // Lo pasamos a string antes date
|
||||
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
|
||||
@@ -19,15 +19,18 @@ export class UpdateServicioDto {
|
||||
|
||||
@IsOptional()
|
||||
@IsDateString({}, { message: 'fechaInicio debe ser una fecha válida' })
|
||||
fechaInicio?: Date;
|
||||
//@Type(() => Date)
|
||||
fechaInicio?: string; // Lo pasamos a string antes date
|
||||
|
||||
@IsOptional()
|
||||
@IsDateString({}, { message: 'fechaFin debe ser una fecha válida' })
|
||||
fechaFin?: Date;
|
||||
//@Type(() => Date)
|
||||
fechaFin?: string; // Lo pasamos a string antes date
|
||||
|
||||
@IsOptional()
|
||||
@IsDateString({}, { message: 'fechaNacimiento debe ser una fecha válida' })
|
||||
fechaNacimiento?: Date;
|
||||
//@Type(() => Date)
|
||||
fechaNacimiento?: string; // Lo pasamos a string antes date
|
||||
|
||||
@IsOptional()
|
||||
@IsString({ message: 'direccion debe ser texto' })
|
||||
|
||||
@@ -1,88 +1,120 @@
|
||||
import { Carrera } from "src/carrera/entities/carrera.entity";
|
||||
import { CuestionarioAlumno } from "src/cuestionario-alumno/entities/cuestionario-alumno.entity";
|
||||
import { CuestionarioAlumno2 } from "src/cuestionario-alumno2/entities/cuestionario-alumno2.entity";
|
||||
import { CuestionarioPrograma } from "src/cuestionario-programa/entities/cuestionario-programa.entity";
|
||||
import { CuestionarioPrograma2 } from "src/cuestionario-programa2/entities/cuestionario-programa2.entity";
|
||||
import { Programa } from "src/programa/entities/programa.entity";
|
||||
import { Status } from "src/status/entities/status.entity";
|
||||
import { Usuario } from "src/usuario/entities/usuario.entity";
|
||||
import { Column, Entity, ManyToOne, PrimaryGeneratedColumn } from "typeorm";
|
||||
import { Carrera } from 'src/carrera/entities/carrera.entity';
|
||||
import { CuestionarioAlumno } from 'src/cuestionario-alumno/entities/cuestionario-alumno.entity';
|
||||
import { CuestionarioAlumno2 } from 'src/cuestionario-alumno2/entities/cuestionario-alumno2.entity';
|
||||
import { CuestionarioPrograma } from 'src/cuestionario-programa/entities/cuestionario-programa.entity';
|
||||
import { CuestionarioPrograma2 } from 'src/cuestionario-programa2/entities/cuestionario-programa2.entity';
|
||||
import { Programa } from 'src/programa/entities/programa.entity';
|
||||
import { Status } from 'src/status/entities/status.entity';
|
||||
import { Usuario } from 'src/usuario/entities/usuario.entity';
|
||||
import {
|
||||
Column,
|
||||
CreateDateColumn,
|
||||
Entity,
|
||||
JoinColumn,
|
||||
ManyToOne,
|
||||
PrimaryGeneratedColumn,
|
||||
UpdateDateColumn,
|
||||
} from 'typeorm';
|
||||
|
||||
@Entity('servicio')
|
||||
export class Servicio {
|
||||
@PrimaryGeneratedColumn()
|
||||
idServicio: number;
|
||||
|
||||
@PrimaryGeneratedColumn()
|
||||
idServicio: number;
|
||||
|
||||
@Column({ type: 'varchar', length: 3 })
|
||||
creditos: string;
|
||||
|
||||
@Column({ type: 'varchar', length: 60 })
|
||||
correo: string;
|
||||
|
||||
@Column({ type: 'varchar', length: 15, nullable: true, default: null })
|
||||
telefono?: string;
|
||||
|
||||
@Column({ type: 'varchar', length: 200, nullable: true, default: null })
|
||||
direccion?: string;
|
||||
|
||||
@Column({ type: 'date' })
|
||||
fechaInicio: Date;
|
||||
|
||||
@Column({ type: 'date' })
|
||||
fechaFin: Date;
|
||||
|
||||
@Column({ type: 'date', nullable: true, default: null })
|
||||
fechaLiberacion?: Date;
|
||||
|
||||
@Column({ type: 'date', nullable: true, default: null })
|
||||
fechaNacimiento?: Date;
|
||||
|
||||
@Column({ type: 'varchar', length: 60 })
|
||||
carpeta: string;
|
||||
|
||||
@Column({ type: 'varchar', length: 60 })
|
||||
cartaAceptacion: string;
|
||||
|
||||
@Column({ type: 'varchar', length: 60, nullable: true, default: null })
|
||||
cartaTermino?: string;
|
||||
|
||||
@Column({ type: 'varchar', length: 60, nullable: true, default: null })
|
||||
informeGlobal?: string;
|
||||
|
||||
@Column({ type: 'varchar', length: 250, nullable: true, default: null })
|
||||
programaInterno?: string;
|
||||
|
||||
@Column({ type: 'varchar', length: 50, nullable: true, default: null })
|
||||
profesor?: string;
|
||||
|
||||
@Column({ type: 'boolean', nullable: true, default: null })
|
||||
vistoBuenoAcatlan?: boolean;
|
||||
@Column({ type: 'varchar', length: 3 })
|
||||
creditos: string;
|
||||
|
||||
@ManyToOne(()=>Usuario,(usuario)=>usuario.servicio)
|
||||
usuario:Usuario
|
||||
@Column({ type: 'varchar', length: 60 })
|
||||
correo: string;
|
||||
|
||||
@ManyToOne(()=>CuestionarioAlumno2,(cuestionarioAlumno2)=>cuestionarioAlumno2.servicio)
|
||||
cuestionarioAlumno2:CuestionarioAlumno2;
|
||||
@Column({ type: 'varchar', length: 15, nullable: true, default: null })
|
||||
telefono?: string;
|
||||
|
||||
@ManyToOne(()=>CuestionarioPrograma2,(cuestionarioPrograma2)=>cuestionarioPrograma2.servicio)
|
||||
cuestionarioPrograma2:CuestionarioPrograma2;
|
||||
@Column({ type: 'varchar', length: 200, nullable: true, default: null })
|
||||
direccion?: string;
|
||||
|
||||
@ManyToOne(()=>CuestionarioPrograma,(cuestionarioPrograma)=>cuestionarioPrograma.servicio)
|
||||
cuestionarioPrograma:CuestionarioPrograma;
|
||||
|
||||
@ManyToOne(()=>CuestionarioAlumno,(cuestionarioAlumno)=>cuestionarioAlumno.servicio)
|
||||
cuestionarioAlumno:CuestionarioAlumno;
|
||||
@Column({ type: 'date' })
|
||||
fechaInicio: string; // Cambios a tipo string antes tenia date
|
||||
|
||||
@ManyToOne(()=>Status,(status)=>status.servicio)
|
||||
status:Status;
|
||||
@Column({ type: 'date' })
|
||||
fechaFin: string; // Cambios a tipo string antes tenia date
|
||||
|
||||
@ManyToOne(()=>Programa,(programa)=>programa.servicio)
|
||||
programa:Programa;
|
||||
@Column({ type: 'date', nullable: true, default: null })
|
||||
fechaLiberacion?: string; // Cambios a tipo string antes tenia date
|
||||
|
||||
@ManyToOne(()=>Carrera,(carrera)=>carrera.servicio)
|
||||
carrera:Carrera;
|
||||
@Column({ type: 'date', nullable: true, default: null })
|
||||
fechaNacimiento?: string; // Cambios a tipo string antes tenia date
|
||||
|
||||
|
||||
@Column({ type: 'varchar', length: 60 })
|
||||
carpeta: string;
|
||||
|
||||
@Column({ type: 'varchar', length: 60 })
|
||||
cartaAceptacion: string;
|
||||
|
||||
@Column({ type: 'varchar', length: 60, nullable: true, default: null })
|
||||
cartaTermino?: string;
|
||||
|
||||
@Column({ type: 'varchar', length: 60, nullable: true, default: null })
|
||||
informeGlobal?: string;
|
||||
|
||||
@Column({ type: 'varchar', length: 250, nullable: true, default: null })
|
||||
programaInterno?: string;
|
||||
|
||||
@Column({ type: 'varchar', length: 50, nullable: true, default: null })
|
||||
profesor?: string;
|
||||
|
||||
@Column({ type: 'boolean', nullable: true, default: null })
|
||||
vistoBuenoAcatlan?: boolean;
|
||||
|
||||
@CreateDateColumn({ name: 'createdAt', type: 'datetime' })
|
||||
createdAt: Date;
|
||||
|
||||
@UpdateDateColumn({ name: 'updatedAt', type: 'datetime' })
|
||||
updatedAt: Date;
|
||||
|
||||
// faltaba createdAT y updatedAT
|
||||
|
||||
@ManyToOne(() => Usuario, (usuario) => usuario.servicio)
|
||||
@JoinColumn({ name: 'idUsuario' })
|
||||
usuario: Usuario;
|
||||
|
||||
@ManyToOne(
|
||||
() => CuestionarioAlumno2,
|
||||
(cuestionarioAlumno2) => cuestionarioAlumno2.servicio,
|
||||
)
|
||||
@JoinColumn({ name: 'idCuestionarioAlumno2' })
|
||||
cuestionarioAlumno2: CuestionarioAlumno2;
|
||||
|
||||
@ManyToOne(
|
||||
() => CuestionarioPrograma2,
|
||||
(cuestionarioPrograma2) => cuestionarioPrograma2.servicio,
|
||||
)
|
||||
@JoinColumn({ name: 'idCuestionarioPrograma2' })
|
||||
cuestionarioPrograma2: CuestionarioPrograma2;
|
||||
|
||||
@ManyToOne(
|
||||
() => CuestionarioPrograma,
|
||||
(cuestionarioPrograma) => cuestionarioPrograma.servicio,
|
||||
)
|
||||
@JoinColumn({ name: 'idCuestionarioPrograma' })
|
||||
cuestionarioPrograma: CuestionarioPrograma;
|
||||
|
||||
@ManyToOne(
|
||||
() => CuestionarioAlumno,
|
||||
(cuestionarioAlumno) => cuestionarioAlumno.servicio,
|
||||
)
|
||||
@JoinColumn({ name: 'idCuestionarioAlumno' })
|
||||
cuestionarioAlumno: CuestionarioAlumno;
|
||||
|
||||
@ManyToOne(() => Status, (status) => status.servicio)
|
||||
@JoinColumn({ name: 'idStatus' })
|
||||
status: Status;
|
||||
|
||||
@ManyToOne(() => Programa, (programa) => programa.servicio)
|
||||
@JoinColumn({ name: 'idPrograma' })
|
||||
programa: Programa;
|
||||
|
||||
@ManyToOne(() => Carrera, (carrera) => carrera.servicios)
|
||||
@JoinColumn({ name: 'idCarrera' })
|
||||
carrera: Carrera;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
import { diskStorage } from 'multer';
|
||||
import { extname } from 'path';
|
||||
|
||||
export const multerConfig = {
|
||||
storage: diskStorage({
|
||||
destination: './server/uploads',
|
||||
filename: (req, file, cb) => {
|
||||
const uniqueName =
|
||||
Date.now() + '-' + Math.round(Math.random() * 1e9);
|
||||
cb(null, uniqueName + extname(file.originalname));
|
||||
},
|
||||
}),
|
||||
};
|
||||
@@ -11,6 +11,8 @@ import {
|
||||
UseInterceptors,
|
||||
Res,
|
||||
ParseIntPipe,
|
||||
Param,
|
||||
Req,
|
||||
} from '@nestjs/common';
|
||||
import {
|
||||
FileInterceptor,
|
||||
@@ -20,30 +22,85 @@ import { ServicioService } from './servicio.service';
|
||||
import { AuthGuard } from '@nestjs/passport';
|
||||
import { CrearServicioDto } from './dto/create-servicio.dto';
|
||||
import { Response } from 'express';
|
||||
import { ServiciosAdminDto } from './dto/servicios-admin.dto';
|
||||
import { ServiciosResponsableDto } from './dto/servicios-responsable.dto';
|
||||
import { RegistroValidadoDto } from './dto/registro-validado.dto';
|
||||
import { multerConfig } from './multer';
|
||||
import { diskStorage } from 'multer';
|
||||
|
||||
@Controller('servicio')
|
||||
export class ServicioController {
|
||||
constructor(private readonly servicioService: ServicioService) {}
|
||||
constructor(private readonly servicioService: ServicioService) { }
|
||||
|
||||
// ------------------ POST ------------------
|
||||
|
||||
// Garegue un nuevo endpoint para hacer pruebas
|
||||
@Post('test-upload')
|
||||
@UseInterceptors(FileInterceptor('file'))
|
||||
uploadTest(
|
||||
@UploadedFile() file: Express.Multer.File,
|
||||
@Req() req: any,
|
||||
) {
|
||||
console.log('FILE:', file);
|
||||
console.log('FILES REQ:', req.file);
|
||||
console.log('FILES BODY:', req.body);
|
||||
return { ok: true };
|
||||
}
|
||||
|
||||
@Post('registro-validado')
|
||||
async registroValidado(
|
||||
@Body() dto: RegistroValidadoDto,
|
||||
): Promise<{ message: string }> {
|
||||
console.log('RegistroValidadoDto recibido:', dto);
|
||||
return this.servicioService.registroValidado(dto);
|
||||
}
|
||||
|
||||
@Post('nuevo')
|
||||
@UseGuards(AuthGuard('jwt'))
|
||||
@UseInterceptors(FileInterceptor('cartaAceptacion'))
|
||||
@UseInterceptors(FileInterceptor('cartaAceptacion', {
|
||||
storage: diskStorage({
|
||||
destination: './server/uploads',
|
||||
filename: (req, file, cb) => {
|
||||
cb(null, Date.now() + '-' + file.originalname);
|
||||
},
|
||||
}),
|
||||
}),
|
||||
)
|
||||
async crearServicio(
|
||||
@UploadedFile() file: Express.Multer.File,
|
||||
@Body('alumno') alumnoJson: string,
|
||||
) {
|
||||
const dto: CrearServicioDto = JSON.parse(alumnoJson);
|
||||
|
||||
console.log('Archivo recibido:', file);
|
||||
|
||||
return await this.servicioService.registrarNuevoServicio(dto, file);
|
||||
}
|
||||
|
||||
// ------------------ GET ------------------
|
||||
|
||||
@Get('todos')
|
||||
//@UseGuards(AuthGuard('jwt'))
|
||||
async obtenerTodosLosServicios() {
|
||||
return this.servicioService.obtenerTodosLosServicios();
|
||||
}
|
||||
|
||||
@Get('admin')
|
||||
@UseGuards(AuthGuard('jwt'))
|
||||
async obtenerAdmin(@Query() query: any) {
|
||||
return this.servicioService.obtenerDetalleServicio(query.idServicio);
|
||||
async obtenerServiciosAdmin(@Query() dto: ServiciosAdminDto) {
|
||||
return await this.servicioService.obtenerServiciosAdmin(dto);
|
||||
}
|
||||
|
||||
@Get('servicios_responsable')
|
||||
@UseGuards(AuthGuard('jwt'))
|
||||
async obtenerServiciosResponsable(@Query() dto: ServiciosResponsableDto) {
|
||||
return await this.servicioService.obtenerServiciosResponsable(dto);
|
||||
}
|
||||
|
||||
@Get('admin/:idServicio')
|
||||
@UseGuards(AuthGuard('jwt'))
|
||||
async obtenerAdmin(@Param('idServicio') idServicio: number) {
|
||||
return this.servicioService.obtenerDetalleServicio(idServicio);
|
||||
}
|
||||
|
||||
@Get('alumno')
|
||||
@@ -62,10 +119,14 @@ export class ServicioController {
|
||||
return res.download(path);
|
||||
}
|
||||
|
||||
// Corregi el endpoint tenia llamando a otrea funcion
|
||||
@Get('reporte')
|
||||
@UseGuards(AuthGuard('jwt'))
|
||||
async generarReporte(@Query() query: any, @Res() res: Response) {
|
||||
const path = await this.servicioService.generarGustavoBazPrada(query.year);
|
||||
async generarReporte(
|
||||
@Query('inicio') inicio: string,
|
||||
@Query('fin') fin: string,
|
||||
@Res() res: Response) {
|
||||
const path = await this.servicioService.generarReporte(inicio, fin);
|
||||
return res.download(path);
|
||||
}
|
||||
|
||||
@@ -78,30 +139,59 @@ export class ServicioController {
|
||||
}
|
||||
|
||||
@Put('carta_aceptacion')
|
||||
@UseGuards(AuthGuard('jwt'))
|
||||
@UseInterceptors(FileInterceptor('cartaAceptacion'))
|
||||
//@UseGuards(AuthGuard('jwt'))
|
||||
@UseInterceptors(
|
||||
FileInterceptor('cartaAceptacion', {
|
||||
storage: diskStorage({
|
||||
destination: './server/uploads',
|
||||
filename: (req, file, cb) => {
|
||||
cb(null, Date.now() + '-' + file.originalname);
|
||||
},
|
||||
}),
|
||||
}),
|
||||
)
|
||||
async subirCartaAceptacion(
|
||||
@UploadedFile() file: Express.Multer.File,
|
||||
@Body('data') dataJson: string,
|
||||
) {
|
||||
const body = JSON.parse(dataJson);
|
||||
return this.servicioService.cartaTermino(body.idServicio, file);
|
||||
console.log('file:', file)
|
||||
return this.servicioService.cartaTermino(body.idServicio, file.filename);
|
||||
}
|
||||
|
||||
@Put('carta_termino')
|
||||
@UseGuards(AuthGuard('jwt'))
|
||||
@UseInterceptors(FileInterceptor('cartaTermino'))
|
||||
@UseInterceptors(
|
||||
FileInterceptor('cartaTermino', {
|
||||
storage: diskStorage({
|
||||
destination: './server/uploads',
|
||||
filename: (req, file, cb) => {
|
||||
cb(null, Date.now() + '-' + file.originalname);
|
||||
},
|
||||
}),
|
||||
}),
|
||||
)
|
||||
async subirCartaTermino(
|
||||
@UploadedFile() file: Express.Multer.File,
|
||||
@Body('data') dataJson: string,
|
||||
) {
|
||||
const body = JSON.parse(dataJson);
|
||||
console.log("file", file);
|
||||
return this.servicioService.subirCartaTermino(body.idServicio, file);
|
||||
}
|
||||
|
||||
@Put('informe_global')
|
||||
@UseGuards(AuthGuard('jwt'))
|
||||
@UseInterceptors(FileInterceptor('informeGlobal'))
|
||||
@UseInterceptors(
|
||||
FileInterceptor('informeGlobal', {
|
||||
storage: diskStorage({
|
||||
destination: './server/uploads',
|
||||
filename: (req, file, cb) => {
|
||||
cb(null, Date.now() + '-' + file.originalname);
|
||||
},
|
||||
}),
|
||||
}),
|
||||
)
|
||||
async subirInformeGlobal(
|
||||
@UploadedFile() file: Express.Multer.File,
|
||||
@Body('data') dataJson: string,
|
||||
@@ -146,13 +236,26 @@ export class ServicioController {
|
||||
{ name: 'cartaAceptacion', maxCount: 1 },
|
||||
{ name: 'cartaTermino', maxCount: 1 },
|
||||
{ name: 'informeGlobal', maxCount: 1 },
|
||||
]),
|
||||
], multerConfig,),
|
||||
|
||||
)
|
||||
async actualizarServicio(
|
||||
@UploadedFiles() files: Record<string, Express.Multer.File[]>,
|
||||
@Body('data') dataJson: string,
|
||||
) {
|
||||
const data = JSON.parse(dataJson);
|
||||
|
||||
return this.servicioService.update(data, files);
|
||||
}
|
||||
|
||||
@Put('registro')
|
||||
@UseGuards(AuthGuard('jwt'))
|
||||
async registro(@Body() body: { idServicio: number }) {
|
||||
try {
|
||||
return this.servicioService.registro(body.idServicio);
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,9 +8,24 @@ import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
import { Servicio } from './entities/servicio.entity';
|
||||
import { Usuario } from 'src/usuario/entities/usuario.entity';
|
||||
import { ArchivoService } from 'src/helpers.services/archivo.service';
|
||||
import { UsuarioModule } from 'src/usuario/usuario.module';
|
||||
import { ProgramaModule } from 'src/programa/programa.module';
|
||||
import { Programa } from 'src/programa/entities/programa.entity';
|
||||
import { Carrera } from 'src/carrera/entities/carrera.entity';
|
||||
import { Auth } from 'googleapis';
|
||||
import { AuthService } from 'src/auth/auth.service';
|
||||
import { AuthModule } from 'src/auth/auth.module';
|
||||
import { Status } from 'src/status/entities/status.entity';
|
||||
import { MulterModule } from '@nestjs/platform-express';
|
||||
|
||||
@Module({
|
||||
imports: [TypeOrmModule.forFeature([Servicio, Usuario])],
|
||||
imports: [
|
||||
TypeOrmModule.forFeature([Servicio, Usuario, Programa, Carrera, Status]),
|
||||
AuthModule,
|
||||
MulterModule.register({
|
||||
dest: './uploads',
|
||||
}),
|
||||
],
|
||||
controllers: [ServicioController],
|
||||
providers: [
|
||||
ServicioService,
|
||||
@@ -19,5 +34,6 @@ import { ArchivoService } from 'src/helpers.services/archivo.service';
|
||||
gmail,
|
||||
ArchivoService,
|
||||
],
|
||||
exports: [TypeOrmModule],
|
||||
})
|
||||
export class ServicioModule {}
|
||||
export class ServicioModule { }
|
||||
|
||||
+396
-181
File diff suppressed because it is too large
Load Diff
@@ -1,8 +1,11 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { StatusService } from './status.service';
|
||||
import { StatusController } from './status.controller';
|
||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
import { Status } from './entities/status.entity';
|
||||
|
||||
@Module({
|
||||
imports: [TypeOrmModule.forFeature([Status])],
|
||||
controllers: [StatusController],
|
||||
providers: [StatusService],
|
||||
})
|
||||
|
||||
@@ -1,16 +1,14 @@
|
||||
import { Usuario } from "src/usuario/entities/usuario.entity";
|
||||
import { Column, Entity, OneToMany, PrimaryGeneratedColumn } from "typeorm";
|
||||
import { Usuario } from 'src/usuario/entities/usuario.entity';
|
||||
import { Column, Entity, OneToMany, PrimaryGeneratedColumn } from 'typeorm';
|
||||
|
||||
@Entity('tipo_usuario')
|
||||
export class TipoUsuario {
|
||||
@PrimaryGeneratedColumn()
|
||||
idTipoUsuario: number;
|
||||
|
||||
@PrimaryGeneratedColumn()
|
||||
idTipoUsuario: number;
|
||||
|
||||
@Column({ type: 'varchar', length: 15 })
|
||||
tipoUsuario: string;
|
||||
|
||||
@OneToMany(()=>Usuario, (usuario)=>usuario.tipoUsuario)
|
||||
usuario:Usuario;
|
||||
@Column({ type: 'varchar', length: 15 })
|
||||
tipoUsuario: string;
|
||||
|
||||
@OneToMany(() => Usuario, (usuario) => usuario.tipoUsuario)
|
||||
usuario: Usuario;
|
||||
}
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
import { Controller, Get, Post, Body, Patch, Param, Delete } from '@nestjs/common';
|
||||
import { TipoUsuarioService } from './tipo-usuario.service';
|
||||
import { CreateTipoUsuarioDto } from './dto/create-tipo-usuario.dto';
|
||||
import { UpdateTipoUsuarioDto } from './dto/update-tipo-usuario.dto';
|
||||
|
||||
@Controller('tipo-usuario')
|
||||
export class TipoUsuarioController {
|
||||
constructor(private readonly tipoUsuarioService: TipoUsuarioService) {}
|
||||
|
||||
@Post()
|
||||
create(@Body() createTipoUsuarioDto: CreateTipoUsuarioDto) {
|
||||
return this.tipoUsuarioService.create(createTipoUsuarioDto);
|
||||
}
|
||||
|
||||
@Get()
|
||||
findAll() {
|
||||
return this.tipoUsuarioService.findAll();
|
||||
}
|
||||
|
||||
@Get(':id')
|
||||
findOne(@Param('id') id: string) {
|
||||
return this.tipoUsuarioService.findOne(+id);
|
||||
}
|
||||
|
||||
@Patch(':id')
|
||||
update(@Param('id') id: string, @Body() updateTipoUsuarioDto: UpdateTipoUsuarioDto) {
|
||||
return this.tipoUsuarioService.update(+id, updateTipoUsuarioDto);
|
||||
}
|
||||
|
||||
@Delete(':id')
|
||||
remove(@Param('id') id: string) {
|
||||
return this.tipoUsuarioService.remove(+id);
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,9 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
import { TipoUsuario } from './entities/tipo-usuario.entity';
|
||||
|
||||
@Module({
|
||||
imports: [TypeOrmModule.forFeature([TipoUsuario])],
|
||||
controllers: [],
|
||||
providers: [],
|
||||
})
|
||||
|
||||
@@ -9,7 +9,6 @@ import {
|
||||
} from 'class-validator';
|
||||
|
||||
export class CreateUsuarioDto {
|
||||
@IsEmail()
|
||||
@IsString()
|
||||
@MaxLength(100)
|
||||
usuario: string;
|
||||
|
||||
@@ -1,13 +1,20 @@
|
||||
import { CasoEspecial } from "src/caso-especial/entities/caso-especial.entity";
|
||||
import { Programa } from "src/programa/entities/programa.entity";
|
||||
import { Servicio } from "src/servicio/entities/servicio.entity";
|
||||
import { TipoUsuario } from "src/tipo-usuario/entities/tipo-usuario.entity";
|
||||
import { Column, Entity, ManyToMany, ManyToOne, OneToMany, PrimaryGeneratedColumn, Unique } from "typeorm";
|
||||
import { CasoEspecial } from 'src/caso-especial/entities/caso-especial.entity';
|
||||
import { Programa } from 'src/programa/entities/programa.entity';
|
||||
import { Servicio } from 'src/servicio/entities/servicio.entity';
|
||||
import { TipoUsuario } from 'src/tipo-usuario/entities/tipo-usuario.entity';
|
||||
import {
|
||||
Column,
|
||||
Entity,
|
||||
JoinColumn,
|
||||
ManyToOne,
|
||||
OneToMany,
|
||||
PrimaryGeneratedColumn,
|
||||
Unique,
|
||||
} from 'typeorm';
|
||||
|
||||
@Entity('usuario')
|
||||
@Unique(['usuario'])
|
||||
export class Usuario {
|
||||
|
||||
@PrimaryGeneratedColumn()
|
||||
idUsuario: number;
|
||||
|
||||
@@ -23,16 +30,16 @@ export class Usuario {
|
||||
@Column({ type: 'boolean', default: true })
|
||||
activo: boolean;
|
||||
|
||||
@ManyToOne(()=>TipoUsuario,(tipoUsuario)=>tipoUsuario.usuario)
|
||||
tipoUsuario:TipoUsuario;
|
||||
@ManyToOne(() => TipoUsuario, (tipoUsuario) => tipoUsuario.usuario)
|
||||
@JoinColumn({ name: 'idTipoUsuario' }) // Talvez faltaba que se llame idTipoUsuario
|
||||
tipoUsuario: TipoUsuario;
|
||||
|
||||
@OneToMany(()=>CasoEspecial,(casoEspecial)=>casoEspecial.usuario)
|
||||
casoEspecial:CasoEspecial[];
|
||||
@OneToMany(() => CasoEspecial, (casoEspecial) => casoEspecial.usuario)
|
||||
casoEspecial: CasoEspecial[];
|
||||
|
||||
@OneToMany(()=>Programa,(programa)=>programa.usuario)
|
||||
programa:Programa[];
|
||||
|
||||
@OneToMany(()=>Servicio,(servicio)=>servicio.usuario)
|
||||
servicio:Servicio[];
|
||||
@OneToMany(() => Programa, (programa) => programa.usuario)
|
||||
programa: Programa[];
|
||||
|
||||
@OneToMany(() => Servicio, (servicio) => servicio.usuario)
|
||||
servicio: Servicio[];
|
||||
}
|
||||
|
||||
@@ -8,6 +8,10 @@ import {
|
||||
Query,
|
||||
ParseIntPipe,
|
||||
UseGuards,
|
||||
UsePipes,
|
||||
ValidationPipe,
|
||||
HttpException,
|
||||
HttpStatus,
|
||||
} from '@nestjs/common';
|
||||
import { UsuarioService } from './usuario.service';
|
||||
import { CreateUsuarioDto } from './dto/create-usuario.dto';
|
||||
@@ -16,7 +20,26 @@ import { UpdateUsuarioDto } from './dto/update-usuario.dto';
|
||||
|
||||
@Controller('usuario')
|
||||
export class UsuarioController {
|
||||
constructor(private readonly usuarioService: UsuarioService) {}
|
||||
constructor(private readonly usuarioService: UsuarioService) { }
|
||||
|
||||
/*Get('todos')
|
||||
//@UseGuards(AuthGuard('jwt'))
|
||||
async obtenerTodosLosServicios() {
|
||||
return this.usuarioService.obtenerTodosLosUsuarios();
|
||||
}*/ //No subir en produccion
|
||||
|
||||
@Post('crearUsuario')
|
||||
@UsePipes(new ValidationPipe({ transform: true }))
|
||||
async create(@Body() createUsuarioDto: CreateUsuarioDto) {
|
||||
try {
|
||||
return await this.usuarioService.create(createUsuarioDto);
|
||||
} catch (error) {
|
||||
throw new HttpException(
|
||||
error.message || 'Error al crear usuario',
|
||||
HttpStatus.BAD_REQUEST,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@Post('escolares/:numeroDeCuenta')
|
||||
async escolares(@Param('numeroDeCuenta') numeroDeCuenta: string) {
|
||||
@@ -24,7 +47,7 @@ export class UsuarioController {
|
||||
}
|
||||
|
||||
@Post('new-password-alumno/:idServicio')
|
||||
@UseGuards(AuthGuard('jwt'))
|
||||
//@UseGuards(AuthGuard('jwt'))
|
||||
async newPasswordAlumno(
|
||||
@Param('idServicio', ParseIntPipe) idServicio: number,
|
||||
) {
|
||||
@@ -56,7 +79,7 @@ export class UsuarioController {
|
||||
}
|
||||
|
||||
@Patch('responsable/:idUsuario')
|
||||
@UseGuards(AuthGuard('jwt'))
|
||||
//seGuards(AuthGuard('jwt'))
|
||||
async actualizarResponsable(
|
||||
@Param('idUsuario', ParseIntPipe) idUsuario: number,
|
||||
@Body() updateUsuarioDto: UpdateUsuarioDto,
|
||||
@@ -67,4 +90,12 @@ export class UsuarioController {
|
||||
updateUsuarioDto.nombre,
|
||||
);
|
||||
}
|
||||
|
||||
@Get('tipos-usuario')
|
||||
async findTiposUsuario() {
|
||||
return await this.usuarioService.findAll();
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -1,9 +1,26 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { UsuarioService } from './usuario.service';
|
||||
import { UsuarioController } from './usuario.controller';
|
||||
import { Usuario } from './entities/usuario.entity';
|
||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
import { CarreraModule } from 'src/carrera/carrera.module';
|
||||
import { ServicioModule } from 'src/servicio/servicio.module';
|
||||
import { gmail } from 'src/helpers.services/gmail.service';
|
||||
import { Auth } from 'googleapis';
|
||||
import { AuthModule } from 'src/auth/auth.module';
|
||||
import { TipoUsuario } from 'src/tipo-usuario/entities/tipo-usuario.entity';
|
||||
import { Carrera } from 'src/carrera/entities/carrera.entity';
|
||||
import { Servicio } from 'src/servicio/entities/servicio.entity';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
TypeOrmModule.forFeature([Usuario, TipoUsuario, Carrera, Servicio]),
|
||||
CarreraModule,
|
||||
ServicioModule,
|
||||
AuthModule,
|
||||
],
|
||||
controllers: [UsuarioController],
|
||||
providers: [UsuarioService],
|
||||
providers: [UsuarioService, gmail],
|
||||
exports: [TypeOrmModule],
|
||||
})
|
||||
export class UsuarioModule {}
|
||||
|
||||
+114
-18
@@ -1,5 +1,7 @@
|
||||
import {
|
||||
BadRequestException,
|
||||
HttpException,
|
||||
HttpStatus,
|
||||
Injectable,
|
||||
NotFoundException,
|
||||
UnauthorizedException,
|
||||
@@ -14,6 +16,8 @@ import { Carrera } from 'src/carrera/entities/carrera.entity';
|
||||
import { Servicio } from 'src/servicio/entities/servicio.entity';
|
||||
import { gmail } from 'src/helpers.services/gmail.service';
|
||||
import { AuthService } from 'src/auth/auth.service';
|
||||
import { TipoUsuario } from 'src/tipo-usuario/entities/tipo-usuario.entity';
|
||||
import * as bcrypt from 'bcrypt';
|
||||
|
||||
@Injectable()
|
||||
export class UsuarioService {
|
||||
@@ -52,24 +56,48 @@ export class UsuarioService {
|
||||
private readonly carreraRepo: Repository<Carrera>,
|
||||
@InjectRepository(Servicio)
|
||||
private readonly servicioRepo: Repository<Servicio>,
|
||||
@InjectRepository(TipoUsuario)
|
||||
private readonly tipoUsurioRepo: Repository<TipoUsuario>,
|
||||
private readonly gmail: gmail,
|
||||
private readonly authService: AuthService,
|
||||
) {}
|
||||
) { }
|
||||
|
||||
async escolares(numeroDeCuenta: string) {
|
||||
let response;
|
||||
try {
|
||||
response = await axios.post(
|
||||
`${process.env.ESCOLARES}${numeroDeCuenta}`,
|
||||
{ password: process.env.ESCOLARES_PASS },
|
||||
if (process.env.MODE == 'pruebas') {
|
||||
/*
|
||||
Quitamos la promesa ya que muestra un error
|
||||
response = new Promise((res) => {
|
||||
res({
|
||||
data: {
|
||||
nombre: 'nombre',
|
||||
carrconst: 'Carrera',
|
||||
avance: '80',
|
||||
},
|
||||
});
|
||||
});
|
||||
*/
|
||||
|
||||
{
|
||||
headers: {
|
||||
'Content-Type': 'application/json', // Tipo de contenido
|
||||
Authorization: `Bearer ${process.env.API_TOKEN}`, // Header de auth
|
||||
return response = {
|
||||
data: {
|
||||
nombre: 'nombre',
|
||||
carrconst: 'Carrera',
|
||||
avance: '80',
|
||||
},
|
||||
},
|
||||
);
|
||||
};
|
||||
} else {
|
||||
response = await axios.post(
|
||||
`${process.env.ESCOLARES}${numeroDeCuenta}`,
|
||||
process.env.ESCOLARES_PASS,
|
||||
{
|
||||
headers: {
|
||||
'Content-Type': 'application/x-www-form-urlencoded',
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
}
|
||||
} catch (error) {
|
||||
throw new UnauthorizedException(
|
||||
'No se pudo conectar con el servicio de escolares',
|
||||
@@ -81,7 +109,7 @@ export class UsuarioService {
|
||||
!response.data.carrconst ||
|
||||
!response.data.avance
|
||||
) {
|
||||
throw new Error(
|
||||
throw new BadRequestException(
|
||||
'El alumno no cumple con los requisitos para realizar el Servicio Social. Si cree que esto es erróneo comunícate al Departamento de Servicio Social y Bolsa de Trabajo.',
|
||||
);
|
||||
}
|
||||
@@ -99,7 +127,7 @@ export class UsuarioService {
|
||||
};
|
||||
|
||||
if (alumno.creditos < this.carreras[alumno.carrera]) {
|
||||
throw new Error('Este alumno no cuenta con los créditos necesarios.');
|
||||
throw new BadRequestException('Este alumno no cuenta con los créditos necesarios.');
|
||||
}
|
||||
while (alumno.nombre.search('') != -1 && alumno.nombre.search('Ã') != -1) {
|
||||
alumno.nombre = alumno.nombre.replace('Ã', 'Ñ');
|
||||
@@ -129,17 +157,17 @@ export class UsuarioService {
|
||||
});
|
||||
alum = await this.userRepo.save(nuevoUsuario);
|
||||
}
|
||||
|
||||
console.log("el alumno es:", alumno);
|
||||
return { ...alumno, idUsuario: alum.idUsuario };
|
||||
}
|
||||
|
||||
async newPasswordAlumno(idServicio: number) {
|
||||
const password = this.authService.generarPassword();
|
||||
const password = await this.authService.generarPassword();
|
||||
|
||||
// Buscar el servicio junto con el usuario
|
||||
const servicio = await this.servicioRepo.findOne({
|
||||
where: { idServicio },
|
||||
relations: ['usuario'], // asegura que traiga la relación
|
||||
relations: ['usuario', 'usuario.tipoUsuario'], // asegura que traiga la relación Le agregue la relacion para traer tipoUsuario
|
||||
});
|
||||
|
||||
if (!servicio) {
|
||||
@@ -153,6 +181,7 @@ export class UsuarioService {
|
||||
}
|
||||
|
||||
// Preparar correo
|
||||
const { preRegistro } = require('../helpers.services/msjCorreos');
|
||||
let correo = preRegistro(password, usuario.nombre);
|
||||
|
||||
// Enviar correo
|
||||
@@ -173,10 +202,10 @@ export class UsuarioService {
|
||||
}
|
||||
|
||||
async newPasswordResponsable(idUsuario: number) {
|
||||
const password = this.authService.generarPassword();
|
||||
const password = await this.authService.generarPassword();
|
||||
|
||||
// Buscar usuario
|
||||
const usuario = await this.userRepo.findOne({ where: { idUsuario } });
|
||||
const usuario = await this.userRepo.findOne({ where: { idUsuario }, relations: ['tipoUsuario'] });
|
||||
|
||||
if (!usuario) {
|
||||
throw new NotFoundException('No existe este Usuario.');
|
||||
@@ -186,7 +215,10 @@ export class UsuarioService {
|
||||
throw new BadRequestException('Este usuario no es de tipo responsable.');
|
||||
}
|
||||
|
||||
|
||||
// Preparar correo
|
||||
const { enviarSec } = require('../helpers.services/msjCorreos');
|
||||
|
||||
const correo = enviarSec(password, usuario.usuario, usuario.nombre);
|
||||
|
||||
// Enviar correo
|
||||
@@ -233,7 +265,10 @@ export class UsuarioService {
|
||||
const dataUpdate: Partial<Usuario> = {};
|
||||
|
||||
// Buscar responsable
|
||||
const responsable = await this.userRepo.findOne({ where: { idUsuario } });
|
||||
const responsable = await this.userRepo.findOne({
|
||||
where: { idUsuario },
|
||||
relations: ['tipoUsuario'],
|
||||
});
|
||||
if (!responsable) {
|
||||
throw new NotFoundException(
|
||||
'No existe este responsable en la base de datos.',
|
||||
@@ -249,6 +284,7 @@ export class UsuarioService {
|
||||
if (correo) {
|
||||
const yaUsado = await this.userRepo.findOne({
|
||||
where: { usuario: correo, idUsuario: Not(idUsuario) },
|
||||
relations: ['tipoUsuario'],
|
||||
});
|
||||
|
||||
if (yaUsado) {
|
||||
@@ -278,4 +314,64 @@ export class UsuarioService {
|
||||
'Se actualizó la información de este responsable de programas correctamente.',
|
||||
};
|
||||
}
|
||||
|
||||
async create(createUsuarioDto: CreateUsuarioDto) {
|
||||
// Verificar si el usuario ya existe
|
||||
const usuarioExistente = await this.userRepo.findOne({
|
||||
where: { usuario: createUsuarioDto.usuario },
|
||||
});
|
||||
|
||||
if (usuarioExistente) {
|
||||
throw new HttpException('El usuario ya existe', HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
|
||||
// Verificar tipo de usuario
|
||||
const tipoUsuario = await this.tipoUsurioRepo.findOne({
|
||||
where: { idTipoUsuario: createUsuarioDto.tipoUsuario },
|
||||
});
|
||||
|
||||
if (!tipoUsuario) {
|
||||
throw new HttpException(
|
||||
'Tipo de usuario no válido',
|
||||
HttpStatus.BAD_REQUEST,
|
||||
);
|
||||
}
|
||||
|
||||
// Hash password
|
||||
let passwordHash = null;
|
||||
if (createUsuarioDto.password) {
|
||||
const saltRounds = 10;
|
||||
passwordHash = await bcrypt.hash(createUsuarioDto.password, saltRounds);
|
||||
}
|
||||
|
||||
// Crear usuario
|
||||
const usuario = this.userRepo.create({
|
||||
...createUsuarioDto,
|
||||
password: passwordHash,
|
||||
tipoUsuario: tipoUsuario,
|
||||
});
|
||||
|
||||
const usuarioGuardado = await this.userRepo.save(usuario);
|
||||
|
||||
// Eliminar password del response
|
||||
const { password, ...result } = usuarioGuardado;
|
||||
return {
|
||||
message: 'Usuario creado exitosamente',
|
||||
usuario: result,
|
||||
};
|
||||
}
|
||||
|
||||
async findAll() {
|
||||
return await this.tipoUsurioRepo.find()
|
||||
}
|
||||
|
||||
/*c obtenerTodosLosUsuarios() {
|
||||
return await this.userRepo.find({
|
||||
relations: ['tipoUsuario'],
|
||||
take: 10,
|
||||
order: {
|
||||
idUsuario: 'DESC', // Ordenar por el más reciente primero
|
||||
},
|
||||
});
|
||||
}*/ // no subir a produccion
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user