diff --git a/src/app.module.ts b/src/app.module.ts index 249a431..d994d30 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -18,6 +18,7 @@ import { InstitucionInfraccionModule } from './institucion-infraccion/institucio import { InstitucionProgramaModule } from './institucion-programa/institucion-programa.module'; import { InstitucionTipoCarritoModule } from './institucion-tipo-carrito/institucion-tipo-carrito.module'; import { InstitucionTipoEntradaModule } from './institucion-tipo-entrada/institucion-tipo-entrada.module'; +import { InstitucionUsuarioModule } from './institucion-usuario/institucion-usuario.module'; import { ModuloModule } from './modulo/modulo.module'; import { MotivoModule } from './motivo/motivo.module'; import { MultaModule } from './multa/multa.module'; @@ -45,6 +46,7 @@ import { InstitucionInfraccion } from './institucion-infraccion/entity/instituci import { InstitucionPrograma } from './institucion-programa/entity/institucion-programa.entity'; import { InstitucionTipoCarrito } from './institucion-tipo-carrito/entity/institucion-tipo-carrito.entity'; import { InstitucionTipoEntrada } from './institucion-tipo-entrada/entity/institucion-tipo-entrada.entity'; +import { InstitucionUsuario } from './institucion-usuario/entity/institucion-usuario.entity'; import { Modulo } from './modulo/entity/modulo.entity'; import { Motivo } from './motivo/entity/motivo.entity'; import { Multa } from './multa/entity/multa.entity'; @@ -90,6 +92,7 @@ import { SoapClientModule } from './soap-client/soap-client.module'; InstitucionPrograma, InstitucionTipoCarrito, InstitucionTipoEntrada, + InstitucionUsuario, Modulo, Motivo, Multa, @@ -133,6 +136,7 @@ import { SoapClientModule } from './soap-client/soap-client.module'; UploadFileModule, UsuarioModule, SoapClientModule, + InstitucionUsuarioModule, ], }) export class AppModule {} diff --git a/src/institucion-carrera/entity/institucion-carrera.entity.ts b/src/institucion-carrera/entity/institucion-carrera.entity.ts index df1134d..1487cb5 100644 --- a/src/institucion-carrera/entity/institucion-carrera.entity.ts +++ b/src/institucion-carrera/entity/institucion-carrera.entity.ts @@ -9,7 +9,7 @@ import { import { Carrera } from './carrera.entity'; import { CarreraPrograma } from '../../carrera-programa/entity/carrera-programa.entity'; import { Institucion } from '../../institucion/entity/institucion.entity'; -import { Usuario } from '../../usuario/entity/usuario.entity'; +import { InstitucionUsuario } from '../../institucion-usuario/entity/institucion-usuario.entity'; @Entity() export class InstitucionCarrera { @@ -35,6 +35,9 @@ export class InstitucionCarrera { ) programas: CarreraPrograma[]; - @OneToMany(() => Usuario, (usuario) => usuario.institucionCarrera) - usuarios: Usuario[]; + @OneToMany( + () => InstitucionUsuario, + (institucionUsuario) => institucionUsuario.institucionCarrera, + ) + usuarios: InstitucionUsuario[]; } diff --git a/src/institucion-usuario/entity/institucion-usuario.entity.ts b/src/institucion-usuario/entity/institucion-usuario.entity.ts new file mode 100644 index 0000000..4ac0be8 --- /dev/null +++ b/src/institucion-usuario/entity/institucion-usuario.entity.ts @@ -0,0 +1,33 @@ +import { + Column, + Entity, + JoinColumn, + ManyToOne, + PrimaryGeneratedColumn, +} from 'typeorm'; +import { InstitucionCarrera } from '../../institucion-carrera/entity/institucion-carrera.entity'; +import { Usuario } from '../../usuario/entity/usuario.entity'; + +@Entity() +export class InstitucionUsuario { + @PrimaryGeneratedColumn() + id_institucion_usuario: number; + + @Column({ type: Boolean, nullable: false, default: true }) + activo: boolean; + + @Column({ type: Boolean, nullable: false, default: false }) + multa: boolean; + + @ManyToOne( + () => InstitucionCarrera, + (institucionCarrera) => institucionCarrera.usuarios, + { eager: true }, + ) + @JoinColumn({ name: 'id_institucion_carrera' }) + institucionCarrera: InstitucionCarrera; + + @ManyToOne(() => Usuario, (usuario) => usuario.instituciones, { eager: true }) + @JoinColumn({ name: 'id_usuario' }) + usuario: Usuario; +} diff --git a/src/institucion-usuario/institucion-usuario.controller.spec.ts b/src/institucion-usuario/institucion-usuario.controller.spec.ts new file mode 100644 index 0000000..45671c7 --- /dev/null +++ b/src/institucion-usuario/institucion-usuario.controller.spec.ts @@ -0,0 +1,18 @@ +import { Test, TestingModule } from '@nestjs/testing'; +import { InstitucionUsuarioController } from './institucion-usuario.controller'; + +describe('InstitucionUsuarioController', () => { + let controller: InstitucionUsuarioController; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + controllers: [InstitucionUsuarioController], + }).compile(); + + controller = module.get(InstitucionUsuarioController); + }); + + it('should be defined', () => { + expect(controller).toBeDefined(); + }); +}); diff --git a/src/institucion-usuario/institucion-usuario.controller.ts b/src/institucion-usuario/institucion-usuario.controller.ts new file mode 100644 index 0000000..6321cb5 --- /dev/null +++ b/src/institucion-usuario/institucion-usuario.controller.ts @@ -0,0 +1,9 @@ +import { Controller } from '@nestjs/common'; +import { AuthGuard } from '@nestjs/passport'; +import { Serealize } from '../interceptors/serialize.interceptor'; +import { InstitucionUsuarioService } from './institucion-usuario.service'; + +@Controller('institucion-usuario') +export class InstitucionUsuarioController { + constructor(private institucionUsuarioService: InstitucionUsuarioService) {} +} diff --git a/src/institucion-usuario/institucion-usuario.module.ts b/src/institucion-usuario/institucion-usuario.module.ts new file mode 100644 index 0000000..271a53f --- /dev/null +++ b/src/institucion-usuario/institucion-usuario.module.ts @@ -0,0 +1,17 @@ +import { Module } from '@nestjs/common'; +import { PassportModule } from '@nestjs/passport'; +import { TypeOrmModule } from '@nestjs/typeorm'; +import { InstitucionUsuarioController } from './institucion-usuario.controller'; +import { InstitucionUsuarioService } from './institucion-usuario.service'; +import { InstitucionUsuario } from './entity/institucion-usuario.entity'; + +@Module({ + imports: [ + PassportModule.register({ defaultStrategy: 'jwt' }), + TypeOrmModule.forFeature([InstitucionUsuario]), + ], + controllers: [InstitucionUsuarioController], + providers: [InstitucionUsuarioService], + exports: [InstitucionUsuarioService], +}) +export class InstitucionUsuarioModule {} diff --git a/src/institucion-usuario/institucion-usuario.service.spec.ts b/src/institucion-usuario/institucion-usuario.service.spec.ts new file mode 100644 index 0000000..4a21213 --- /dev/null +++ b/src/institucion-usuario/institucion-usuario.service.spec.ts @@ -0,0 +1,18 @@ +import { Test, TestingModule } from '@nestjs/testing'; +import { InstitucionUsuarioService } from './institucion-usuario.service'; + +describe('InstitucionUsuarioService', () => { + let service: InstitucionUsuarioService; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + providers: [InstitucionUsuarioService], + }).compile(); + + service = module.get(InstitucionUsuarioService); + }); + + it('should be defined', () => { + expect(service).toBeDefined(); + }); +}); diff --git a/src/institucion-usuario/institucion-usuario.service.ts b/src/institucion-usuario/institucion-usuario.service.ts new file mode 100644 index 0000000..a385df6 --- /dev/null +++ b/src/institucion-usuario/institucion-usuario.service.ts @@ -0,0 +1,58 @@ +import { ConflictException, Injectable } from '@nestjs/common'; +import { InjectRepository } from '@nestjs/typeorm'; +import { Repository } from 'typeorm'; +import { InstitucionCarrera } from '../institucion-carrera/entity/institucion-carrera.entity'; +import { InstitucionUsuario } from './entity/institucion-usuario.entity'; +import { Usuario } from '../usuario/entity/usuario.entity'; + +@Injectable() +export class InstitucionUsuarioService { + constructor( + @InjectRepository(InstitucionUsuario) + private repository: Repository, + ) {} + + create(institucionCarrera: InstitucionCarrera, usuario: Usuario) { + return this.repository + .save(this.repository.create({ institucionCarrera, usuario })) + .then((institucionUsuario) => ({ + message: `Se asignó la carrera: ${institucionUsuario.institucionCarrera.carrera.carrera} al alumno: ${institucionUsuario.usuario.usuario}.`, + institucionUsuario, + })); + } + + findById(id_institucion_usuario: number) { + return this.repository + .findOne({ id_institucion_usuario }) + .then((institucionUsuario) => { + if (!institucionUsuario) + throw new ConflictException('No existe este id institución usuario.'); + return institucionUsuario; + }); + } + + findByUsuarioIdInstitucionCarrera( + usuario: Usuario, + institucionCarrera: InstitucionCarrera, + campo: string, + ) { + return this.repository + .findOne({ usuario, institucionCarrera }) + .then((institucionUsuario) => { + if (!institucionUsuario) + throw new ConflictException( + `No se encontró información de este número de ${campo} en esta institución.`, + ); + return institucionUsuario; + }); + } + + update(attrs: Partial) { + return this.findById(attrs.id_institucion_usuario).then( + (institucionUsuario) => { + Object.assign(institucionUsuario, attrs); + return this.repository.save(institucionUsuario); + }, + ); + } +} diff --git a/src/multa/multa.module.ts b/src/multa/multa.module.ts index a01bd50..a52904c 100644 --- a/src/multa/multa.module.ts +++ b/src/multa/multa.module.ts @@ -6,6 +6,7 @@ import { Multa } from './entity/multa.entity'; import { EquipoModule } from '../equipo/equipo.module'; import { InstitucionModule } from '../institucion/institucion.module'; import { InstitucionInfraccionModule } from '../institucion-infraccion/institucion-infraccion.module'; +import { InstitucionUsuarioModule } from '../institucion-usuario/institucion-usuario.module'; import { OperadorModule } from '../operador/operador.module'; import { PrestamoModule } from '../prestamo/prestamo.module'; import { UsuarioModule } from '../usuario/usuario.module'; @@ -15,6 +16,7 @@ import { UsuarioModule } from '../usuario/usuario.module'; EquipoModule, InstitucionModule, InstitucionInfraccionModule, + InstitucionUsuarioModule, OperadorModule, forwardRef(() => PrestamoModule), TypeOrmModule.forFeature([Multa]), diff --git a/src/multa/multa.service.ts b/src/multa/multa.service.ts index 2a4927d..6f392b4 100644 --- a/src/multa/multa.service.ts +++ b/src/multa/multa.service.ts @@ -10,6 +10,7 @@ import { Prestamo } from '../prestamo/entity/prestamo.entity'; import { EquipoService } from '../equipo/equipo.service'; import { InstitucionService } from '../institucion/institucion.service'; import { InstitucionInfraccionService } from '../institucion-infraccion/institucion-infraccion.service'; +import { InstitucionUsuarioService } from '../institucion-usuario/institucion-usuario.service'; import { OperadorService } from '../operador/operador.service'; import { PrestamoService } from '../prestamo/prestamo.service'; import { UsuarioService } from '../usuario/usuario.service'; @@ -21,6 +22,7 @@ export class MultaService { private equipoService: EquipoService, private institucionService: InstitucionService, private institucionInfraccionService: InstitucionInfraccionService, + private institucionUsuarioService: InstitucionUsuarioService, private operadorService: OperadorService, private prestamoService: PrestamoService, private usuarioService: UsuarioService, @@ -71,7 +73,7 @@ export class MultaService { .then((existeMulta) => { if (existeMulta) throw new ConflictException( - 'Ya existe una multa asignada a este prestamo.', + 'Ya existe una multa asignada a este préstamo.', ); if (retraso) { data.retraso = true; @@ -85,8 +87,17 @@ export class MultaService { return this.repository.save(this.repository.create(data)); }) .then((_) => { - prestamo.usuario.multa = true; - return this.usuarioService.update(prestamo.usuario); + for (let i = 0; prestamo.usuario.instituciones.length; i++) + if ( + prestamo.usuario.instituciones[i].institucionCarrera.institucion + .id_institucion === + institucionInfraccion.institucion.id_institucion + ) { + prestamo.usuario.instituciones[i].multa = true; + return this.institucionUsuarioService.update( + prestamo.usuario.instituciones[i], + ); + } }); } @@ -180,10 +191,20 @@ export class MultaService { for (let i = 0; i < multas.length; i++) if (ahora.diff(moment(multas[i].fecha_fin)) > 0) { multas[i].activo = false; - multas[i].prestamo.usuario.multa = false; await this.usuarioService .update(multas[i].prestamo.usuario) .then((_) => this.repository.save(multas[i])); + for (let j = 0; multas[i].prestamo.usuario.instituciones.length; j++) + if ( + multas[i].prestamo.usuario.instituciones[j].institucionCarrera + .institucion.id_institucion === + multas[i].opeardorMulta.institucion.id_institucion + ) { + multas[i].prestamo.usuario.instituciones[j].multa = false; + await this.institucionUsuarioService.update( + multas[i].prestamo.usuario.instituciones[j], + ); + } } }); } diff --git a/src/prestamo/prestamo.service.ts b/src/prestamo/prestamo.service.ts index 50be02a..21b55be 100644 --- a/src/prestamo/prestamo.service.ts +++ b/src/prestamo/prestamo.service.ts @@ -90,7 +90,7 @@ export class PrestamoService { .then((_) => this.repository.save(prestamo)) .then((_) => { this.appGateway.actualizarOperador( - prestamo.usuario.institucionCarrera.institucion.id_institucion, + prestamo.equipo.carrito.modulo.institucion.id_institucion, ); return { message: 'Se canceló correctamente este préstamo.', @@ -145,10 +145,15 @@ export class PrestamoService { // if (ahora < horaMin) // throw new Error('Aún es muy temprano para realizar un préstamo.'); // } - if (usuario.multa) - throw new ConflictException( - 'Este usuario tiene una multa activa. No puede pedir equipos de cómputo.', - ); + for (let i = 0; i < usuario.instituciones.length; i++) + if ( + usuario.instituciones[i].institucionCarrera.institucion + .id_institucion === modulo.institucion.id_institucion && + usuario.instituciones[i].multa + ) + throw new ConflictException( + 'Este usuario tiene una multa activa. No puede pedir equipos de cómputo.', + ); return this.repository .findOne({ activo: true, usuario }) .then((existePrestamo) => { @@ -188,9 +193,7 @@ export class PrestamoService { ), ) .then((prestamo) => { - this.appGateway.actualizarOperador( - prestamo.usuario.institucionCarrera.institucion.id_institucion, - ); + this.appGateway.actualizarOperador(modulo.institucion.id_institucion); return prestamo; }); } diff --git a/src/upload-file/upload-file.module.ts b/src/upload-file/upload-file.module.ts index dc9865d..0b0b0e0 100644 --- a/src/upload-file/upload-file.module.ts +++ b/src/upload-file/upload-file.module.ts @@ -11,6 +11,7 @@ import { InstitucionCarreraModule } from '../institucion-carrera/institucion-car import { InstitucionProgramaModule } from '../institucion-programa/institucion-programa.module'; import { InstitucionTipoCarritoModule } from '../institucion-tipo-carrito/institucion-tipo-carrito.module'; import { InstitucionTipoEntradaModule } from '../institucion-tipo-entrada/institucion-tipo-entrada.module'; +import { InstitucionUsuarioModule } from '../institucion-usuario/institucion-usuario.module'; import { ModuloModule } from '../modulo/modulo.module'; import { TipoUsuarioModule } from '../tipo-usuario/tipo-usuario.module'; import { UsuarioModule } from '../usuario/usuario.module'; @@ -26,6 +27,7 @@ import { UsuarioModule } from '../usuario/usuario.module'; InstitucionProgramaModule, InstitucionTipoCarritoModule, InstitucionTipoEntradaModule, + InstitucionUsuarioModule, ModuloModule, MulterModule.register({ dest: './upload', diff --git a/src/upload-file/upload-file.service.ts b/src/upload-file/upload-file.service.ts index 4038ac0..b181488 100644 --- a/src/upload-file/upload-file.service.ts +++ b/src/upload-file/upload-file.service.ts @@ -1,7 +1,7 @@ import * as csvtojson from 'csvtojson'; import { BadRequestException, Injectable } from '@nestjs/common'; import { Equipo } from '../equipo/entity/equipo.entity'; -import { Usuario } from '../usuario/entity/usuario.entity'; +import { InstitucionUsuario } from '../institucion-usuario/entity/institucion-usuario.entity'; import { CarritoService } from '../carrito/carrito.service'; import { EquipoService } from '../equipo/equipo.service'; import { EquipoProgramaService } from '../equipo-programa/equipo-programa.service'; @@ -11,6 +11,7 @@ import { InstitucionCarreraService } from '../institucion-carrera/institucion-ca import { InstitucionProgramaService } from '../institucion-programa/institucion-programa.service'; import { InstitucionTipoCarritoService } from '../institucion-tipo-carrito/institucion-tipo-carrito.service'; import { InstitucionTipoEntradaService } from '../institucion-tipo-entrada/institucion-tipo-entrada.service'; +import { InstitucionUsuarioService } from '../institucion-usuario/institucion-usuario.service'; import { ModuloService } from '../modulo/modulo.service'; import { TipoUsuarioService } from '../tipo-usuario/tipo-usuario.service'; import { UsuarioService } from '../usuario/usuario.service'; @@ -29,6 +30,7 @@ export class UploadFileService { private institucionProgramaService: InstitucionProgramaService, private institucionTipoCarritoService: InstitucionTipoCarritoService, private institucionTipoEntradaService: InstitucionTipoEntradaService, + private institucionUsuarioService: InstitucionUsuarioService, private moduloService: ModuloService, private tipoUsuarioService: TipoUsuarioService, private usuarioService: UsuarioService, @@ -245,7 +247,8 @@ export class UploadFileService { const institucion = await this.institucionService.findById(id_institucion); const errores: string[] = []; const mensajes: string[] = []; - const usuariosNuevos: Usuario[] = []; + const usuariosActualizados: InstitucionUsuario[] = []; + const usuariosNuevos: InstitucionUsuario[] = []; return csvtojson() .fromFile(path) @@ -253,24 +256,12 @@ export class UploadFileService { for (let i = 0; i < usuarios.length; i++) { let error = this.errorBase(i); - if ( - !usuarios[i].numero_cuenta || - !usuarios[i].tipo_usuario || - !usuarios[i].nombres || - !usuarios[i].apellido_m || - !usuarios[i].apellido_p - ) { + if (!usuarios[i].numero_cuenta || !usuarios[i].tipo_usuario) { if (!usuarios[i].numero_cuenta) error += ' falta del campo numero_cuenta'; if (error != this.errorBase(i)) error += ','; if (!usuarios[i].tipo_usuario) error += ' falta del campo tipo_usuario'; - if (error != this.errorBase(i)) error += ','; - if (!usuarios[i].nombres) error += ' falta del campo nombres'; - if (error != this.errorBase(i)) error += ','; - if (!usuarios[i].apellido_m) error += ' falta del campo apellido_m'; - if (error != this.errorBase(i)) error += ','; - if (!usuarios[i].apellido_p) error += ' falta del campo apellido_p'; errores.push(`${error}.`); continue; } @@ -316,21 +307,54 @@ export class UploadFileService { continue; } if (usuario) { + let existeInstitucionUsuario: InstitucionUsuario = null; + + for (let i = 0; i < usuario.instituciones.length; i++) + if ( + usuario.instituciones[i].institucionCarrera + .id_institucion_carrera === + institucionCarrera.id_institucion_carrera + ) { + existeInstitucionUsuario = usuario.instituciones[i]; + break; + } + if (existeInstitucionUsuario && !existeInstitucionUsuario.activo) { + existeInstitucionUsuario.activo = true; + await this.institucionUsuarioService.update( + existeInstitucionUsuario, + ); + } else if (!existeInstitucionUsuario) + await this.institucionUsuarioService + .create(institucionCarrera, usuario) + .then(({ message, institucionUsuario }) => { + usuariosActualizados.push(institucionUsuario); + mensajes.push(message); + }); if ( usuario.tipoUsuario.id_tipo_usuario != tipoUsuario.id_tipo_usuario - ) + ) { usuario.tipoUsuario = tipoUsuario; - if (!usuario.activo) usuario.activo = true; + await this.usuarioService + .update(usuario, false) + .then(({ message }) => mensajes.push(message)); + } + } else { if ( - institucionCarrera && - usuario.institucionCarrera.id_institucion_carrera != - institucionCarrera.id_institucion_carrera - ) - usuario.institucionCarrera = institucionCarrera; - await this.usuarioService - .update(usuario, false) - .then(({ message }) => mensajes.push(message)); - } else + !usuarios[i].nombres || + !usuarios[i].apellido_m || + !usuarios[i].apellido_p + ) { + if (error != this.errorBase(i)) error += ','; + if (!usuarios[i].nombres) error += ' falta del campo nombres'; + if (error != this.errorBase(i)) error += ','; + if (!usuarios[i].apellido_m) + error += ' falta del campo apellido_m'; + if (error != this.errorBase(i)) error += ','; + if (!usuarios[i].apellido_p) + error += ' falta del campo apellido_p'; + errores.push(`${error}.`); + continue; + } await this.usuarioService .create( usuarios[i].numero_cuenta, @@ -340,7 +364,11 @@ export class UploadFileService { tipoUsuario, institucionCarrera, ) - .then((usuarioNuevo) => usuariosNuevos.push(usuarioNuevo)); + .then(({ message, institucionUsuario }) => { + usuariosNuevos.push(institucionUsuario); + mensajes.push(message); + }); + } } return { message: 'Se subió y cargó correctamente tu archivo csv.', diff --git a/src/usuario/dto/input/dgae.dto.ts b/src/usuario/dto/input/dgae.dto.ts index 5eb9729..e945b1a 100644 --- a/src/usuario/dto/input/dgae.dto.ts +++ b/src/usuario/dto/input/dgae.dto.ts @@ -1,6 +1,6 @@ import { IsNumberString, IsString } from 'class-validator'; -export class UsuarioDgaeDto { +export class DgaeInputDto { @IsNumberString() id_institucion_carrera: string; diff --git a/src/usuario/dto/input/dgp.dto.ts b/src/usuario/dto/input/dgp.dto.ts index b769d12..26c77ea 100644 --- a/src/usuario/dto/input/dgp.dto.ts +++ b/src/usuario/dto/input/dgp.dto.ts @@ -1,6 +1,6 @@ -import { IsNumberString, IsString } from 'class-validator'; +import { IsString } from 'class-validator'; -export class UsuarioDgpDto { +export class DgpInputDto { @IsString() rfc: string; diff --git a/src/usuario/entity/usuario.entity.ts b/src/usuario/entity/usuario.entity.ts index 3dc324f..8dee7f8 100644 --- a/src/usuario/entity/usuario.entity.ts +++ b/src/usuario/entity/usuario.entity.ts @@ -6,7 +6,7 @@ import { OneToMany, PrimaryGeneratedColumn, } from 'typeorm'; -import { InstitucionCarrera } from '../../institucion-carrera/entity/institucion-carrera.entity'; +import { InstitucionUsuario } from '../../institucion-usuario/entity/institucion-usuario.entity'; import { Prestamo } from '../../prestamo/entity/prestamo.entity'; import { TipoUsuario } from '../../tipo-usuario/entity/tipo-usuario.entity'; @@ -21,35 +21,30 @@ export class Usuario { @Column({ type: String, nullable: false, length: 60, default: '' }) correo: string; - @Column({ type: Boolean, nullable: false, default: false }) - multa: boolean; - @Column({ type: String, nullable: false, length: 100 }) nombre: string; @Column({ type: String, nullable: true, length: 60, default: null }) - password?: string; + password: string; @Column({ type: String, nullable: true, length: 10, default: null }) - telefono?: string; + telefono: string; @Column({ type: String, nullable: false, length: 10 }) usuario: string; - @ManyToOne( - () => InstitucionCarrera, - (institucionCarrera) => institucionCarrera.usuarios, - { eager: true }, - ) - @JoinColumn({ name: 'id_institucion_carrera' }) - institucionCarrera: InstitucionCarrera; - @ManyToOne(() => TipoUsuario, (tipoUsuario) => tipoUsuario.usuarios, { eager: true, }) @JoinColumn({ name: 'id_tipo_usuario' }) tipoUsuario: TipoUsuario; + @OneToMany( + () => InstitucionUsuario, + (institucionUsuario) => institucionUsuario.usuario, + ) + instituciones: InstitucionUsuario[]; + @OneToMany(() => Prestamo, (prestamo) => prestamo.usuario) prestamos: Prestamo[]; } diff --git a/src/usuario/usuario.controller.ts b/src/usuario/usuario.controller.ts index e081fb0..15015c8 100644 --- a/src/usuario/usuario.controller.ts +++ b/src/usuario/usuario.controller.ts @@ -11,8 +11,6 @@ import { AuthGuard } from '@nestjs/passport'; import { ApiBody, ApiOperation, ApiQuery, ApiTags } from '@nestjs/swagger'; import { Serealize } from '../interceptors/serialize.interceptor'; import { UsuarioService } from './usuario.service'; -import { UsuarioDgaeDto } from './dto/input/dgae.dto'; -import { UsuarioDgpDto } from './dto/input/dgp.dto'; import { UsuarioRegistrarDto } from './dto/input/registrar.dto'; import { UsuarioUpdateDto } from './dto/input/update.dto'; import { UsuarioUsuariosDto } from './dto/input/usuarios.dto'; @@ -20,6 +18,8 @@ import { UsuarioDto } from './dto/input/usuario.dto'; import { EscolaresOutputDto } from './dto/output/escolares.dto'; import { UsuarioOutputDto } from './dto/output/usuario.dto'; import { UsuariosOutputDto } from './dto/output/usuarios.dto'; +import { DgaeInputDto } from './dto/input/dgae.dto'; +import { DgpInputDto } from './dto/input/dgp.dto'; @Controller('usuario') @ApiTags('usuario') @@ -41,7 +41,7 @@ export class UsuarioController { name: 'id_institucion_carrera', type: 'string', }) - dgae(@Query() query: UsuarioDgaeDto) { + dgae(@Query() query: DgaeInputDto) { return this.usuarioService.DGAE( query.usuario, parseInt(query.id_institucion_carrera), @@ -59,7 +59,7 @@ export class UsuarioController { type: 'string', }) @ApiQuery({ description: 'RFC del profesor.', name: 'rfc', type: 'string' }) - dgp(@Query() query: UsuarioDgpDto) { + dgp(@Query() query: DgpInputDto) { return this.usuarioService.DGP(query.usuario, query.rfc); } diff --git a/src/usuario/usuario.module.ts b/src/usuario/usuario.module.ts index f4ba0ad..07def22 100644 --- a/src/usuario/usuario.module.ts +++ b/src/usuario/usuario.module.ts @@ -8,6 +8,7 @@ import { BcryptModule } from '../bcrypt/bcrypt.module'; import { NodemailerModule } from '../nodemailer/nodemailer.module'; import { InstitucionModule } from '../institucion/institucion.module'; import { InstitucionCarreraModule } from '../institucion-carrera/institucion-carrera.module'; +import { InstitucionUsuarioModule } from '../institucion-usuario/institucion-usuario.module'; import { SoapClientModule } from '../soap-client/soap-client.module'; import { TipoUsuarioModule } from '../tipo-usuario/tipo-usuario.module'; @@ -16,6 +17,7 @@ import { TipoUsuarioModule } from '../tipo-usuario/tipo-usuario.module'; BcryptModule, InstitucionModule, InstitucionCarreraModule, + InstitucionUsuarioModule, NodemailerModule, PassportModule.register({ defaultStrategy: 'jwt' }), SoapClientModule, diff --git a/src/usuario/usuario.service.ts b/src/usuario/usuario.service.ts index 60a3789..6b3192f 100644 --- a/src/usuario/usuario.service.ts +++ b/src/usuario/usuario.service.ts @@ -4,18 +4,17 @@ import { NotFoundException, } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; -import { FindOperator, IsNull, Like, Not, Repository } from 'typeorm'; -import { Institucion } from '../institucion/entity/institucion.entity'; +import { createQueryBuilder, Repository } from 'typeorm'; import { InstitucionCarrera } from '../institucion-carrera/entity/institucion-carrera.entity'; import { TipoUsuario } from '../tipo-usuario/entity/tipo-usuario.entity'; import { Usuario } from './entity/usuario.entity'; import { BcryptService } from '../bcrypt/bcrypt.service'; import { InstitucionService } from '../institucion/institucion.service'; import { InstitucionCarreraService } from '../institucion-carrera/institucion-carrera.service'; +import { InstitucionUsuarioService } from '../institucion-usuario/institucion-usuario.service'; import { NodemailerService } from '../nodemailer/nodemailer.service'; import { SoapClientService } from '../soap-client/soap-client.service'; import { TipoUsuarioService } from '../tipo-usuario/tipo-usuario.service'; -import { Carrera } from '../institucion-carrera/entity/carrera.entity'; @Injectable() export class UsuarioService { @@ -24,6 +23,7 @@ export class UsuarioService { private bcryptService: BcryptService, private institucionService: InstitucionService, private institucionCarreraService: InstitucionCarreraService, + private institucionUsuarioService: InstitucionUsuarioService, private nodemailerService: NodemailerService, private soapClientService: SoapClientService, private tipoUsuarioService: TipoUsuarioService, @@ -35,14 +35,17 @@ export class UsuarioService { tipoUsuario: TipoUsuario, institucionCarrera: InstitucionCarrera, ) { - return this.repository.save( - this.repository.create({ - nombre, - tipoUsuario, - usuario, - institucionCarrera, - }), - ); + return this.repository + .save( + this.repository.create({ + nombre, + tipoUsuario, + usuario, + }), + ) + .then((usuario) => + this.institucionUsuarioService.create(institucionCarrera, usuario), + ); } correoPassword(password: string) { @@ -67,22 +70,44 @@ export class UsuarioService {

Pc Puma Solicita

`; } - DGAE(usuario: string, id_institucion_carrera: number) { - return this.findByUsuario(usuario).then(async (existeUsuario) => { - /* Falta conexión a soap */ - if (existeUsuario.password) - throw new ConflictException('Ya fue regisrado este usuario.'); - return existeUsuario; - }); + async DGAE(usuario: string, id_institucion_carrera: number) { + const institucionCarrera = await this.institucionCarreraService.findById( + id_institucion_carrera, + ); + + return this.findByUsuario(usuario, true, true).then( + async (existeUsuario) => { + /* Falta conexión a soap */ + if (existeUsuario.password) + throw new ConflictException( + 'Ya fue regisrado este número de cuenta.', + ); + return this.institucionUsuarioService.findByUsuarioIdInstitucionCarrera( + existeUsuario, + institucionCarrera, + 'cuenta', + ); + }, + ); } - DGP(usuario: string, rfc: string) { - return this.findByUsuario(usuario).then(async (existeUsuario) => { - /* Falta conexión a soap */ - if (existeUsuario.password) - throw new ConflictException('Ya fue regisrado este usuario.'); - return existeUsuario; - }); + async DGP(usuario: string, rfc: string) { + const institucionCarrera = await this.institucionCarreraService.findById(1); + + return this.findByUsuario(usuario, true, true).then( + async (existeUsuario) => { + /* Falta conexión a soap */ + if (existeUsuario.password) + throw new ConflictException( + 'Ya fue regisrado este número de trabajador.', + ); + return this.institucionUsuarioService.findByUsuarioIdInstitucionCarrera( + existeUsuario, + institucionCarrera, + 'trabajador', + ); + }, + ); } async findAll(filtros: { @@ -93,13 +118,15 @@ export class UsuarioService { nombre?: string; usuario?: string; }) { - const busqueda: { - password: FindOperator; - institucionCarrera: { carrera?: Carrera; institucion?: Institucion }; - nombre?: FindOperator; - tipoUsuario?: TipoUsuario; - usuario?: FindOperator; - } = { password: Not(IsNull()), institucionCarrera: {} }; + const query = createQueryBuilder('u') + .innerJoinAndSelect('u.tipoUsuario', 'tu') + .innerJoinAndSelect('u.instituciones', 'is') + .innerJoinAndSelect('is.institucionCarrera', 'ic') + .innerJoinAndSelect('ic.institucion', 'i') + .innerJoinAndSelect('ic.carrera', 'c') + .take(25) + .skip((parseInt(filtros.pagina) - 1) * 25) + .where('u.password IS NOT NULL'); const carrera = filtros.id_carrera ? await this.institucionCarreraService.findCarreraByIdCarrera( parseInt(filtros.id_carrera), @@ -114,25 +141,27 @@ export class UsuarioService { ) : null; - if (filtros.usuario) busqueda.usuario = Like(`%${filtros.usuario}%`); - if (filtros.nombre) busqueda.nombre = Like(`%${filtros.nombre}%`); - if (carrera) busqueda.institucionCarrera.carrera = carrera; - if (institucion) busqueda.institucionCarrera.institucion = institucion; - if (tipoUsuario) busqueda.tipoUsuario = tipoUsuario; - return this.repository.findAndCount({ - join: { - alias: 'u', - innerJoinAndSelect: { - ic: 'u.institucionCarrera', - c: 'ic.carrera', - i: 'ic.institucion', - }, - }, - where: busqueda, - skip: (parseInt(filtros.pagina) - 1) * 25, - take: 25, - order: { usuario: 'ASC' }, - }); + if (filtros.usuario) + query.andWhere('u.usuario LIKE :usuario', { + usuario: `%${filtros.usuario}%`, + }); + if (filtros.nombre) + query.andWhere('u.nombre LIKE :nombre', { + nombre: `%${filtros.nombre}%`, + }); + if (carrera) + query.andWhere('c.id_carrera = :id_carrera', { + id_carrera: carrera.id_carrera, + }); + if (institucion) + query.andWhere('i.id_institucion = :id_institucion', { + id_institucion: institucion.id_institucion, + }); + if (tipoUsuario) + query.andWhere('tu.id_tipo_usuario = :id_tipo_usuario', { + id_tipo_usuario: tipoUsuario.id_tipo_usuario, + }); + return query.getManyAndCount(); } findById(id_usuario: number, validarNoExiste = true, password = false) { @@ -179,32 +208,31 @@ export class UsuarioService { }), ) .then((_) => ({ - message: 'Se reseteo correctamente la constraseña del usuario.', + message: 'Se cambió correctamente la constraseña del usuario.', })); } - registrar(id_usuario: number, telefono: string, correo?: string) { + registrar(id_institucion_usuario: number, telefono: string, correo?: string) { const password = this.generarPassword(); - return this.findById(id_usuario) - .then((usuario) => { + return this.institucionUsuarioService + .findById(id_institucion_usuario) + .then((institucionUsuario) => { + const usuario = institucionUsuario.usuario; + const institucion = institucionUsuario.institucionCarrera.institucion; + if (usuario.password) throw new ConflictException( 'Ya fue registrado este número de cuenta.', ); - if ( - !usuario.institucionCarrera.institucion.email_institucional && - !correo - ) - throw new ConflictException('No se envió un correo.'); - else if ( - !usuario.institucionCarrera.institucion.email_institucional && - correo - ) + if (!institucion.email_institucional && !correo) + throw new ConflictException( + 'No se envió un correo electrónico para el regístro.', + ); + else if (!institucion.email_institucional && correo) usuario.correo = correo; - else if (usuario.institucionCarrera.institucion.email_institucional) - usuario.correo = - usuario.usuario + usuario.institucionCarrera.institucion.dominio; + else if (institucion.email_institucional) + usuario.correo = `${usuario.usuario}${institucion.dominio}`; usuario.telefono = telefono; usuario.password = this.bcryptService.encriptar(password); return this.repository.save(usuario); @@ -218,7 +246,7 @@ export class UsuarioService { ) .then((_) => ({ message: - 'Se creó correctamente tu cuenta, ingresa a tu correo institucional y consultar tu contraseña para este servicio.', + 'Se creó correctamente tu cuenta, ingresa a tu correo institucional y consulta tu contraseña para acceder a este servicio.', })); }