25 Commits

Author SHA1 Message Date
edreitega 98e5159f2f Merge pull request 'Optimización de consulta de préstamos activos (SPI-007)' (#5) from dev into master
Reviewed-on: #5
2026-06-30 17:21:08 +00:00
edreitega f86c4d4f2a Merge pull request 'SPI-007: optimizar count de préstamos activos con vista ligera' (#4) from feature/SPI-007-prestamos-activos-timeout into dev
Reviewed-on: #4
2026-06-29 17:31:33 +00:00
Edrei Téllez ffb2a1d64a SPI-007: optimizar count de préstamos activos con vista ligera
Separar find (full view) del count (informacion_prestamo_view) en el path
activo=true con paginación para evitar timeout por COUNT sobre 8 JOINs.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-29 11:06:27 -06:00
edreitega 4660214cd7 Merge pull request 'SEC-001: migrar hCaptcha a Cloudflare Turnstile en API (prod)' (#3) from dev into master
Reviewed-on: #3
2026-06-23 12:58:11 -06:00
edreitega 8e74802de7 Merge pull request 'SEC-001: migrar HcaptchaGuard a TurnstileGuard con siteverify Cloudflare.' (#2) from feature/SEC-001-turnstile into dev
Reviewed-on: #2
2026-06-23 10:37:03 -06:00
Edrei Téllez ce1d1396e0 SEC-001: migrar HcaptchaGuard a TurnstileGuard con siteverify Cloudflare.
Bypass solo en desarrollo; pruebas y producción validan header turnstile vía HTTPS nativo.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-23 10:29:57 -06:00
edreitega e5076603fd Merge pull request 'alinear dev con master (prod)' (#1) from master into dev
Reviewed-on: #1
2026-06-04 18:25:37 -06:00
puma99 662f195918 nuvos tipos de carrito locker 2023-12-15 11:41:09 -06:00
Lemuel Márquez b485fffb41 sql/12-institucion_tipo_carrito.sql 2023-09-18 09:29:47 -06:00
Lemuel Marquez eefcc15760 hora del servidor 2023-05-30 15:15:10 -06:00
puma99 f5e768ca99 dejar de cancelar al minuto 2023-04-18 09:27:06 -06:00
puma99 ae770a4998 mejoras 2023-04-17 23:32:31 -06:00
puma99 b520156b13 cambio de horario 2023-04-17 23:12:14 -06:00
puma99 591089b8e1 regresar carrera profesor 2023-04-13 20:58:49 -06:00
puma99 711e8f8916 correccion tablas 2023-03-15 20:08:59 -06:00
puma99 c1b525be80 corregido 2023-03-14 13:08:52 -06:00
puma99 43f56a7c4b correciones 2023-03-14 10:39:11 -06:00
puma99 0960a4c37a listo 2023-02-27 15:23:51 -06:00
puma99 a4d80e3c31 una grafica faltante 2023-02-27 15:02:17 -06:00
puma99 1c83cb9fb8 todas las gráficas 2023-02-22 12:04:46 -06:00
puma99 8a56cf7524 mini cambios 2023-02-21 14:21:45 -06:00
puma99 632c0c4442 paso a institucion usuario 2023-02-17 10:18:34 -06:00
puma99 4a941e4757 sin reparar 2023-02-10 12:47:35 -06:00
puma99 4e61a200c2 list para crear cosas 2023-02-10 12:39:23 -06:00
puma99 dda3fc5987 sin console logs 2023-02-10 12:37:08 -06:00
36 changed files with 569 additions and 293 deletions
-11
View File
@@ -25,7 +25,6 @@
"class-validator": "^0.13.2", "class-validator": "^0.13.2",
"csvtojson": "^2.0.10", "csvtojson": "^2.0.10",
"dotenv": "^16.0.3", "dotenv": "^16.0.3",
"hcaptcha": "^0.1.1",
"moment": "^2.29.4", "moment": "^2.29.4",
"mysql2": "^2.3.3", "mysql2": "^2.3.3",
"nodemailer": "^6.7.8", "nodemailer": "^6.7.8",
@@ -5049,11 +5048,6 @@
"resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz",
"integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ=="
}, },
"node_modules/hcaptcha": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/hcaptcha/-/hcaptcha-0.1.1.tgz",
"integrity": "sha512-iMrDmH2VpIEKOrcKWidVjI89FdDKTEdZ7PfPWkP27sTazIIkob8YfdY2ezaufAnWBiUUcvzsn0qF+dyXtBH2Vw=="
},
"node_modules/hexoid": { "node_modules/hexoid": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/hexoid/-/hexoid-1.0.0.tgz", "resolved": "https://registry.npmjs.org/hexoid/-/hexoid-1.0.0.tgz",
@@ -13436,11 +13430,6 @@
"resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz",
"integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ=="
}, },
"hcaptcha": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/hcaptcha/-/hcaptcha-0.1.1.tgz",
"integrity": "sha512-iMrDmH2VpIEKOrcKWidVjI89FdDKTEdZ7PfPWkP27sTazIIkob8YfdY2ezaufAnWBiUUcvzsn0qF+dyXtBH2Vw=="
},
"hexoid": { "hexoid": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/hexoid/-/hexoid-1.0.0.tgz", "resolved": "https://registry.npmjs.org/hexoid/-/hexoid-1.0.0.tgz",
-1
View File
@@ -37,7 +37,6 @@
"class-validator": "^0.13.2", "class-validator": "^0.13.2",
"csvtojson": "^2.0.10", "csvtojson": "^2.0.10",
"dotenv": "^16.0.3", "dotenv": "^16.0.3",
"hcaptcha": "^0.1.1",
"moment": "^2.29.4", "moment": "^2.29.4",
"mysql2": "^2.3.3", "mysql2": "^2.3.3",
"nodemailer": "^6.7.8", "nodemailer": "^6.7.8",
+4 -4
View File
@@ -2,7 +2,7 @@ import { Body, Controller, Get, Post, UseGuards } from '@nestjs/common';
import { AuthGuard } from '@nestjs/passport'; import { AuthGuard } from '@nestjs/passport';
import { ApiBody, ApiOperation, ApiTags } from '@nestjs/swagger'; import { ApiBody, ApiOperation, ApiTags } from '@nestjs/swagger';
import { Serealize } from '../interceptors/serialize.interceptor'; import { Serealize } from '../interceptors/serialize.interceptor';
import { HcaptchaGuard } from '../guards/hcaptcha.guard'; import { TurnstileGuard } from '../guards/turnstile.guard';
import { AuthService } from './auth.service'; import { AuthService } from './auth.service';
import { LoginAdminDto } from './dto/input/login-admin.dto'; import { LoginAdminDto } from './dto/input/login-admin.dto';
import { LoginOperadorDto } from './dto/input/login-operador.dto'; import { LoginOperadorDto } from './dto/input/login-operador.dto';
@@ -15,7 +15,7 @@ export class AuthController {
constructor(private authService: AuthService) {} constructor(private authService: AuthService) {}
@Serealize(AuthTokenOutputDto) @Serealize(AuthTokenOutputDto)
@UseGuards(HcaptchaGuard) @UseGuards(TurnstileGuard)
@Post('login-admin') @Post('login-admin')
@ApiOperation({ description: 'Login del admin.' }) @ApiOperation({ description: 'Login del admin.' })
@ApiBody({ @ApiBody({
@@ -27,7 +27,7 @@ export class AuthController {
} }
@Serealize(AuthTokenOutputDto) @Serealize(AuthTokenOutputDto)
@UseGuards(HcaptchaGuard) @UseGuards(TurnstileGuard)
@Post('login-operador') @Post('login-operador')
@ApiOperation({ description: 'Login del operador.' }) @ApiOperation({ description: 'Login del operador.' })
@ApiBody({ @ApiBody({
@@ -45,7 +45,7 @@ export class AuthController {
} }
@Serealize(AuthTokenOutputDto) @Serealize(AuthTokenOutputDto)
@UseGuards(HcaptchaGuard) @UseGuards(TurnstileGuard)
@Post('login-usuario') @Post('login-usuario')
@ApiOperation({ description: 'Login del usuario.' }) @ApiOperation({ description: 'Login del usuario.' })
@ApiBody({ @ApiBody({
+20 -1
View File
@@ -6,7 +6,13 @@ import {
Injectable, Injectable,
} from '@nestjs/common'; } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm'; import { InjectRepository } from '@nestjs/typeorm';
import { FindManyOptions, FindOptionsWhere, Repository } from 'typeorm'; import {
Between,
FindManyOptions,
FindOptionsWhere,
MoreThanOrEqual,
Repository,
} from 'typeorm';
import { Carrito } from '../carrito/entity/carrito.entity'; import { Carrito } from '../carrito/entity/carrito.entity';
import { CarritoMotivo } from './entity/carrito-motivo.entity'; import { CarritoMotivo } from './entity/carrito-motivo.entity';
import { Operador } from '../operador/entity/operador.entity'; import { Operador } from '../operador/entity/operador.entity';
@@ -79,6 +85,8 @@ export class CarritoMotivoService {
admin: Operador, admin: Operador,
filtros: { filtros: {
carrito?: string; carrito?: string;
fechaFin?: string;
fechaInicio?: string;
id_institucion?: string; id_institucion?: string;
id_marca?: string; id_marca?: string;
id_modelo?: string; id_modelo?: string;
@@ -109,6 +117,17 @@ export class CarritoMotivoService {
}; };
if (filtros.carrito) busquedaCarrito.carrito = filtros.carrito; if (filtros.carrito) busquedaCarrito.carrito = filtros.carrito;
if (filtros.fechaInicio) {
if (filtros.fechaFin)
busqueda.fecha_creacion = Between(
new Date(`${filtros.fechaInicio} 00:00`),
new Date(`${filtros.fechaFin} 23:59`),
);
else
busqueda.fecha_creacion = MoreThanOrEqual(
new Date(`${filtros.fechaInicio} 00:00`),
);
}
if (admin.institucion) if (admin.institucion)
busquedaCarrito.modulo = { institucion: admin.institucion }; busquedaCarrito.modulo = { institucion: admin.institucion };
else if (institucion) busquedaCarrito.modulo = { institucion }; else if (institucion) busquedaCarrito.modulo = { institucion };
@@ -1,4 +1,5 @@
import { import {
IsDateString,
IsNotEmpty, IsNotEmpty,
IsNumberString, IsNumberString,
IsOptional, IsOptional,
@@ -11,6 +12,14 @@ export class LaboratorioMovilDto {
@IsOptional() @IsOptional()
carrito?: string; carrito?: string;
@IsDateString()
@IsOptional()
fechaFin?: string;
@IsDateString()
@IsOptional()
fechaInicio?: string;
@IsNumberString() @IsNumberString()
@IsOptional() @IsOptional()
id_institucion?: string; id_institucion?: string;
+5 -3
View File
@@ -32,7 +32,9 @@ export class CronService {
this.appGateway.actualizarOperador( this.appGateway.actualizarOperador(
prestamos[i].equipo.carrito.modulo.institucion.id_institucion, prestamos[i].equipo.carrito.modulo.institucion.id_institucion,
); );
this.appGateway.actualizarUsuario(prestamos[i].usuario.id_usuario); this.appGateway.actualizarUsuario(
prestamos[i].institucionUsuario.usuario.id_usuario,
);
}); });
} }
}); });
@@ -56,7 +58,7 @@ export class CronService {
prestamos[i].equipo.carrito.modulo.institucion.id_institucion, prestamos[i].equipo.carrito.modulo.institucion.id_institucion,
); );
this.appGateway.actualizarUsuario( this.appGateway.actualizarUsuario(
prestamos[i].usuario.id_usuario, prestamos[i].institucionUsuario.usuario.id_usuario,
); );
}); });
} }
@@ -88,7 +90,7 @@ export class CronService {
// Quitamos multas en institución usuario // Quitamos multas en institución usuario
this.institucionUsuarioService.updateMulta( this.institucionUsuarioService.updateMulta(
multas[i].institucionInfraccion.institucion, multas[i].institucionInfraccion.institucion,
multas[i].prestamo.usuario, multas[i].prestamo.institucionUsuario.usuario,
false, false,
), ),
); );
+9 -1
View File
@@ -1,7 +1,15 @@
import { IsNumberString, IsOptional } from 'class-validator'; import { IsDateString, IsNumberString, IsOptional } from 'class-validator';
export class IdInstitucionOptionalDto { export class IdInstitucionOptionalDto {
@IsNumberString() @IsNumberString()
@IsOptional() @IsOptional()
id_institucion?: string; id_institucion?: string;
@IsDateString()
@IsOptional()
fechaFin?: string;
@IsDateString()
@IsOptional()
fechaInicio?: string;
} }
-37
View File
@@ -1,37 +0,0 @@
const { verify } = require('hcaptcha');
import {
BadRequestException,
CanActivate,
ExecutionContext,
ForbiddenException,
Injectable,
InternalServerErrorException,
} from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { Observable } from 'rxjs';
@Injectable()
export class HcaptchaGuard implements CanActivate {
constructor(private configService: ConfigService) {}
canActivate(
context: ExecutionContext,
): boolean | Promise<boolean> | Observable<boolean> {
const secret = this.configService.get<string>('HCAPTCHA_KEY');
const token = context.switchToHttp().getRequest().headers.hcaptcha;
if (this.configService.get<string>('STATE') !== 'produccion') return true;
if (!token)
throw new BadRequestException('No se mando un token de hcaptcha.');
return verify(secret, token)
.then((data) => {
if (data.success === true) return true;
else throw new ForbiddenException('El token de hcaptcha no es válido.');
})
.catch((err) => {
throw new InternalServerErrorException(
'Ocurrió un error con el hcaptcha.',
);
});
}
}
+80
View File
@@ -0,0 +1,80 @@
import {
BadRequestException,
CanActivate,
ExecutionContext,
ForbiddenException,
Injectable,
InternalServerErrorException,
} from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import * as https from 'https';
import { Observable } from 'rxjs';
function verifyTurnstile(
secret: string,
token: string,
): Promise<{ success: boolean }> {
const body = new URLSearchParams({ secret, response: token }).toString();
return new Promise((resolve, reject) => {
const req = https.request(
{
hostname: 'challenges.cloudflare.com',
path: '/turnstile/v0/siteverify',
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': Buffer.byteLength(body),
},
},
(res) => {
let data = '';
res.on('data', (chunk) => {
data += chunk;
});
res.on('end', () => {
try {
resolve(JSON.parse(data));
} catch (err) {
reject(err);
}
});
},
);
req.on('error', reject);
req.write(body);
req.end();
});
}
@Injectable()
export class TurnstileGuard implements CanActivate {
constructor(private configService: ConfigService) {}
canActivate(
context: ExecutionContext,
): boolean | Promise<boolean> | Observable<boolean> {
if (this.configService.get<string>('STATE') === 'desarrollo') return true;
const token = context.switchToHttp().getRequest().headers.turnstile;
if (!token)
throw new BadRequestException('No se envió un token de turnstile.');
const secret = this.configService.get<string>('TURNSTILE_SECRET_KEY');
return verifyTurnstile(secret, token)
.then((data) => {
if (data.success === true) return true;
throw new ForbiddenException('El token de turnstile no es válido.');
})
.catch((err) => {
if (
err instanceof ForbiddenException ||
err instanceof BadRequestException
)
throw err;
throw new InternalServerErrorException(
'Ocurrió un error con turnstile.',
);
});
}
}
@@ -30,7 +30,7 @@ export class InstitucionCarreraService {
.findById(id_institucion) .findById(id_institucion)
.then((institucion) => .then((institucion) =>
this.institucionCarreraRepository.find({ this.institucionCarreraRepository.find({
where: { carrera: { id_carrera: Not(1) }, institucion }, where: { institucion },
order: { carrera: { carrera: 'ASC' } }, order: { carrera: { carrera: 'ASC' } },
}), }),
); );
@@ -0,0 +1,16 @@
import { Expose, Type } from 'class-transformer';
import { InstitucionCarreaOutputDto } from '../../../institucion-carrera/dto/output/institucion-carrera.dto';
import { UsuariosOutputDto } from '../../../usuario/dto/output/usuarios.dto';
export class UsuarioInstitucionCarreraMinOutputDto {
@Expose()
id_institucion_usuario;
@Expose()
@Type(() => InstitucionCarreaOutputDto)
institucionCarrera;
@Expose()
@Type(() => UsuariosOutputDto)
usuario;
}
@@ -3,11 +3,11 @@ import {
Entity, Entity,
JoinColumn, JoinColumn,
ManyToOne, ManyToOne,
// OneToMany, OneToMany,
PrimaryGeneratedColumn, PrimaryGeneratedColumn,
} from 'typeorm'; } from 'typeorm';
import { InstitucionCarrera } from '../../institucion-carrera/entity/institucion-carrera.entity'; import { InstitucionCarrera } from '../../institucion-carrera/entity/institucion-carrera.entity';
// import { Prestamo } from '../../prestamo/entity/prestamo.entity'; import { Prestamo } from '../../prestamo/entity/prestamo.entity';
import { Usuario } from '../../usuario/entity/usuario.entity'; import { Usuario } from '../../usuario/entity/usuario.entity';
@Entity() @Entity()
@@ -39,6 +39,6 @@ export class InstitucionUsuario {
@JoinColumn({ name: 'id_usuario' }) @JoinColumn({ name: 'id_usuario' })
usuario: Usuario; usuario: Usuario;
// @OneToMany(() => Prestamo, (prestamo) => prestamo.institucionUsuario) @OneToMany(() => Prestamo, (prestamo) => prestamo.institucionUsuario)
// prestamos: Prestamo[]; prestamos: Prestamo[];
} }
@@ -86,6 +86,7 @@ export class ModuloMotivoController {
description: 'Id de la institución.', description: 'Id de la institución.',
name: 'id_institucion', name: 'id_institucion',
type: 'string', type: 'string',
required: false,
}) })
reporteActividadEspecial( reporteActividadEspecial(
@Request() req, @Request() req,
@@ -94,9 +95,6 @@ export class ModuloMotivoController {
const admin: Operador = req.user.operador; const admin: Operador = req.user.operador;
this.validarUsuarioService.validarSuperAdminAdmin(admin); this.validarUsuarioService.validarSuperAdminAdmin(admin);
return this.moduloMotivoService.findAllActividadEspecial( return this.moduloMotivoService.findAllActividadEspecial(admin, query);
admin,
parseInt(query.id_institucion),
);
} }
} }
+29 -4
View File
@@ -6,7 +6,13 @@ import {
Injectable, Injectable,
} from '@nestjs/common'; } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm'; import { InjectRepository } from '@nestjs/typeorm';
import { FindManyOptions, FindOptionsWhere, Repository } from 'typeorm'; import {
Between,
FindManyOptions,
FindOptionsWhere,
MoreThanOrEqual,
Repository,
} from 'typeorm';
import { Modulo } from '../modulo/entity/modulo.entity'; import { Modulo } from '../modulo/entity/modulo.entity';
import { ModuloMotivo } from './entity/modulo-motivo.entity'; import { ModuloMotivo } from './entity/modulo-motivo.entity';
import { Operador } from '../operador/entity/operador.entity'; import { Operador } from '../operador/entity/operador.entity';
@@ -44,20 +50,39 @@ export class ModuloMotivoService {
async findAllActividadEspecial( async findAllActividadEspecial(
admin: Operador, admin: Operador,
id_institucion?: number, filtros: {
fechaFin?: string;
fechaInicio?: string;
id_institucion?: string;
},
): Promise<ModuloMotivo[]> { ): Promise<ModuloMotivo[]> {
const institucion = id_institucion const institucion = filtros.id_institucion
? await this.institucionService.findById(id_institucion) ? await this.institucionService.findById(parseInt(filtros.id_institucion))
: null; : null;
const busqueda: FindOptionsWhere<ModuloMotivo> = {}; const busqueda: FindOptionsWhere<ModuloMotivo> = {};
if (admin.institucion) busqueda.modulo = { institucion: admin.institucion }; if (admin.institucion) busqueda.modulo = { institucion: admin.institucion };
else if (institucion) busqueda.modulo = { institucion: institucion }; else if (institucion) busqueda.modulo = { institucion: institucion };
if (filtros.fechaInicio) {
if (filtros.fechaFin)
busqueda.fecha_creacion = Between(
new Date(`${filtros.fechaInicio} 00:00`),
new Date(`${filtros.fechaFin} 23:59`),
);
else
busqueda.fecha_creacion = MoreThanOrEqual(
new Date(`${filtros.fechaInicio} 00:00`),
);
}
return this.repository.find({ return this.repository.find({
join: { join: {
alias: 'mmo', alias: 'mmo',
innerJoinAndSelect: { m: 'mmo.modulo', i: 'm.institucion' }, innerJoinAndSelect: { m: 'mmo.modulo', i: 'm.institucion' },
}, },
order: {
operador: { institucion: { institucion: 'ASC' } },
id_motivo: 'ASC',
},
where: busqueda, where: busqueda,
}); });
} }
@@ -2,6 +2,7 @@ import { DataSource, ViewEntity, ViewColumn } from 'typeorm';
import { Infraccion } from '../../../institucion-infraccion/entity/infraccion.entity'; import { Infraccion } from '../../../institucion-infraccion/entity/infraccion.entity';
import { Institucion } from '../../../institucion/entity/institucion.entity'; import { Institucion } from '../../../institucion/entity/institucion.entity';
import { InstitucionInfraccion } from '../../../institucion-infraccion/entity/institucion-infraccion.entity'; import { InstitucionInfraccion } from '../../../institucion-infraccion/entity/institucion-infraccion.entity';
import { InstitucionUsuario } from '../../../institucion-usuario/entity/institucion-usuario.entity';
import { Multa } from '../multa.entity'; import { Multa } from '../multa.entity';
import { Operador } from '../../../operador/entity/operador.entity'; import { Operador } from '../../../operador/entity/operador.entity';
import { Prestamo } from '../../../prestamo/entity/prestamo.entity'; import { Prestamo } from '../../../prestamo/entity/prestamo.entity';
@@ -24,7 +25,8 @@ import { Usuario } from '../../../usuario/entity/usuario.entity';
.addSelect('ii.id_institucion', 'id_institucion') .addSelect('ii.id_institucion', 'id_institucion')
.addSelect('om.operador', 'operador') .addSelect('om.operador', 'operador')
.addSelect('p.id_equipo', 'id_equipo') .addSelect('p.id_equipo', 'id_equipo')
.addSelect('p.id_usuario', 'id_usuario') .addSelect('p.id_institucion_usuario', 'id_institucion_usuario')
.addSelect('iu.id_usuario', 'id_usuario')
.addSelect('inf.infraccion', 'infraccion') .addSelect('inf.infraccion', 'infraccion')
.addSelect('i.institucion', 'institucion') .addSelect('i.institucion', 'institucion')
.addSelect('u.usuario', 'usuario') .addSelect('u.usuario', 'usuario')
@@ -38,8 +40,13 @@ import { Usuario } from '../../../usuario/entity/usuario.entity';
.innerJoin(Operador, 'om', 'om.id_operador = mu.id_operador') .innerJoin(Operador, 'om', 'om.id_operador = mu.id_operador')
.innerJoin(Prestamo, 'p', 'p.id_prestamo = mu.id_prestamo') .innerJoin(Prestamo, 'p', 'p.id_prestamo = mu.id_prestamo')
.innerJoin(Infraccion, 'inf', 'inf.id_infraccion = ii.id_infraccion') .innerJoin(Infraccion, 'inf', 'inf.id_infraccion = ii.id_infraccion')
.innerJoin(Usuario, 'u', 'u.id_usuario = p.id_usuario') .innerJoin(
.innerJoin(Institucion, 'i', 'i.id_institucion = ii.id_institucion'), InstitucionUsuario,
'iu',
'iu.id_institucion_usuario = p.id_institucion_usuario',
)
.innerJoin(Institucion, 'i', 'i.id_institucion = ii.id_institucion')
.innerJoin(Usuario, 'u', 'u.id_usuario = iu.id_usuario'),
}) })
export class FullInformacionMultaView { export class FullInformacionMultaView {
@ViewColumn() @ViewColumn()
@@ -60,15 +67,18 @@ export class FullInformacionMultaView {
@ViewColumn() @ViewColumn()
id_equipo: number; id_equipo: number;
@ViewColumn()
id_institucion: number;
@ViewColumn() @ViewColumn()
id_infraccion: number; id_infraccion: number;
@ViewColumn()
id_institucion: number;
@ViewColumn() @ViewColumn()
id_institucion_infraccion: number; id_institucion_infraccion: number;
@ViewColumn()
id_institucion_usuario: number;
@ViewColumn() @ViewColumn()
id_operador: number; id_operador: number;
@@ -1,8 +1,9 @@
import { DataSource, ViewEntity, ViewColumn } from 'typeorm'; import { DataSource, ViewEntity, ViewColumn } from 'typeorm';
import { InstitucionInfraccion } from '../../../institucion-infraccion/entity/institucion-infraccion.entity'; import { InstitucionInfraccion } from '../../../institucion-infraccion/entity/institucion-infraccion.entity';
import { InstitucionUsuario } from '../../../institucion-usuario/entity/institucion-usuario.entity';
import { Multa } from '../multa.entity'; import { Multa } from '../multa.entity';
import { Prestamo } from '../../../prestamo/entity/prestamo.entity';
import { Operador } from '../../../operador/entity/operador.entity'; import { Operador } from '../../../operador/entity/operador.entity';
import { Prestamo } from '../../../prestamo/entity/prestamo.entity';
@ViewEntity({ @ViewEntity({
expression: (dataSource: DataSource) => expression: (dataSource: DataSource) =>
@@ -17,7 +18,8 @@ import { Operador } from '../../../operador/entity/operador.entity';
.addSelect('mu.retraso', 'retraso') .addSelect('mu.retraso', 'retraso')
.addSelect('ii.id_infraccion', 'id_infraccion') .addSelect('ii.id_infraccion', 'id_infraccion')
.addSelect('ii.id_institucion', 'id_institucion') .addSelect('ii.id_institucion', 'id_institucion')
.addSelect('p.id_usuario', 'id_usuario') .addSelect('p.id_institucion_usuario', 'id_institucion_usuario')
.addSelect('iu.id_usuario', 'id_usuario')
.from(Multa, 'mu') .from(Multa, 'mu')
.innerJoin( .innerJoin(
InstitucionInfraccion, InstitucionInfraccion,
@@ -25,7 +27,12 @@ import { Operador } from '../../../operador/entity/operador.entity';
'ii.id_institucion_infraccion = mu.id_institucion_infraccion', 'ii.id_institucion_infraccion = mu.id_institucion_infraccion',
) )
.innerJoin(Prestamo, 'p', 'p.id_prestamo = mu.id_prestamo') .innerJoin(Prestamo, 'p', 'p.id_prestamo = mu.id_prestamo')
.innerJoin(Operador, 'om', 'om.id_operador = mu.id_operador'), .innerJoin(Operador, 'om', 'om.id_operador = mu.id_operador')
.innerJoin(
InstitucionUsuario,
'iu',
'iu.id_institucion_usuario = p.id_institucion_usuario',
),
}) })
export class InformacionMultaView { export class InformacionMultaView {
@ViewColumn() @ViewColumn()
@@ -46,6 +53,9 @@ export class InformacionMultaView {
@ViewColumn() @ViewColumn()
id_institucion_infraccion: number; id_institucion_infraccion: number;
@ViewColumn()
id_institucion_usuario: number;
@ViewColumn() @ViewColumn()
id_operador: number; id_operador: number;
+20 -13
View File
@@ -89,7 +89,7 @@ export class MultaService {
// Multamos al usuario en todas las carreras a las que pertenece en esa institución // Multamos al usuario en todas las carreras a las que pertenece en esa institución
this.institucionUsuarioService.updateMulta( this.institucionUsuarioService.updateMulta(
operadorMulta.institucion, operadorMulta.institucion,
prestamo.usuario, prestamo.institucionUsuario.usuario,
true, true,
), ),
); );
@@ -159,7 +159,9 @@ export class MultaService {
operadorMulta: { id_operador: infoMultas[i].id_operador }, operadorMulta: { id_operador: infoMultas[i].id_operador },
prestamo: { prestamo: {
id_prestamo: infoMultas[i].id_prestamo, id_prestamo: infoMultas[i].id_prestamo,
usuario: { id_usuario: infoMultas[i].id_usuario }, institucionUsuario: {
usuario: { id_usuario: infoMultas[i].id_usuario },
},
}, },
}), }),
); );
@@ -232,13 +234,17 @@ export class MultaService {
return this.repository.find({ return this.repository.find({
join: { join: {
alias: 'mu', alias: 'mu',
innerJoin: { p: 'mu.prestamo', u: 'p.usuario' }, innerJoin: {
p: 'mu.prestamo',
iu: 'p.institucionUsuario',
u: 'iu.usuario',
},
innerJoinAndSelect: { innerJoinAndSelect: {
ii: 'mu.institucionInfraccion', ii: 'mu.institucionInfraccion',
i: 'ii.institucion', i: 'ii.institucion',
}, },
}, },
where: { activo: true, prestamo: { usuario } }, where: { activo: true, prestamo: { institucionUsuario: { usuario } } },
}); });
} }
@@ -267,10 +273,12 @@ export class MultaService {
}, },
prestamo: { prestamo: {
id_prestamo: infoMulta.id_prestamo, id_prestamo: infoMulta.id_prestamo,
usuario: { institucionUsuario: {
id_usuario: infoMulta.id_usuario, usuario: {
usuario: infoMulta.usuario, id_usuario: infoMulta.id_usuario,
nombre: infoMulta.nombre, usuario: infoMulta.usuario,
nombre: infoMulta.nombre,
},
}, },
}, },
}); });
@@ -328,7 +336,7 @@ export class MultaService {
// Multamos al usuario en todas las carreras a las que pertenece en esa institución // Multamos al usuario en todas las carreras a las que pertenece en esa institución
this.institucionUsuarioService.updateMulta( this.institucionUsuarioService.updateMulta(
operador.institucion, operador.institucion,
prestamo.usuario, prestamo.institucionUsuario.usuario,
true, true,
), ),
); );
@@ -344,11 +352,10 @@ export class MultaService {
const multa = await this.repository const multa = await this.repository
.createQueryBuilder('mu') .createQueryBuilder('mu')
.innerJoinAndSelect('mu.prestamo', 'p') .innerJoinAndSelect('mu.prestamo', 'p')
.innerJoinAndSelect('p.usuario', 'u')
.innerJoin( .innerJoin(
'u.instituciones', 'p.institucionUsuario',
'is', 'iu',
'is.id_institucion_usuario = :id_institucion_usuario', 'iu.id_institucion_usuario = :id_institucion_usuario',
{ id_institucion_usuario: institucionUsuario.id_institucion_usuario }, { id_institucion_usuario: institucionUsuario.id_institucion_usuario },
) )
.where('mu.activo = 1') .where('mu.activo = 1')
-9
View File
@@ -47,9 +47,6 @@ export class PasscodeController {
const operador: Operador = req.user.operador; const operador: Operador = req.user.operador;
const modulo: Modulo = req.user.modulo; const modulo: Modulo = req.user.modulo;
console.log(operador);
console.log(body);
console.log();
this.validarUsuarioService.validarSoloOperador(operador); this.validarUsuarioService.validarSoloOperador(operador);
return this.passcodeService.devolverEquipo(operador, modulo, body.passcode); return this.passcodeService.devolverEquipo(operador, modulo, body.passcode);
} }
@@ -67,9 +64,6 @@ export class PasscodeController {
const operador: Operador = req.user.operador; const operador: Operador = req.user.operador;
const modulo: Modulo = req.user.modulo; const modulo: Modulo = req.user.modulo;
console.log(operador);
console.log(body);
console.log();
this.validarUsuarioService.validarSoloOperador(operador); this.validarUsuarioService.validarSoloOperador(operador);
return this.passcodeService.entregarEquipo( return this.passcodeService.entregarEquipo(
operador, operador,
@@ -99,9 +93,6 @@ export class PasscodeController {
prestamo(@Request() req, @Query() query: PrestamoDto) { prestamo(@Request() req, @Query() query: PrestamoDto) {
const operador: Operador = req.user.operador; const operador: Operador = req.user.operador;
console.log(operador);
console.log(query);
console.log();
this.validarUsuarioService.validarSoloOperador(operador); this.validarUsuarioService.validarSoloOperador(operador);
return this.passcodeService.findPasscode( return this.passcodeService.findPasscode(
query.passcode, query.passcode,
+3
View File
@@ -4,6 +4,9 @@ export class PedirDto {
@IsInt() @IsInt()
id_modulo: number; id_modulo: number;
@IsInt()
id_institucion_usuario: number;
@IsInt() @IsInt()
id_tipo_carrito: number; id_tipo_carrito: number;
+3 -3
View File
@@ -1,6 +1,6 @@
import { Expose, Type } from 'class-transformer'; import { Expose, Type } from 'class-transformer';
import { EquiposOutputDto } from '../../../equipo/dto/output/equipos.dto'; import { EquiposOutputDto } from '../../../equipo/dto/output/equipos.dto';
import { UsuariosOutputDto } from '../../../usuario/dto/output/usuarios.dto'; import { UsuarioInstitucionCarreraMinOutputDto } from '../../../institucion-usuario/dto/output/usuario-institucion-carrera-min.dto';
export class ActivosOutputDto { export class ActivosOutputDto {
@Expose() @Expose()
@@ -23,6 +23,6 @@ export class ActivosOutputDto {
equipo; equipo;
@Expose() @Expose()
@Type(() => UsuariosOutputDto) @Type(() => UsuarioInstitucionCarreraMinOutputDto)
usuario; institucionUsuario;
} }
@@ -1,5 +1,5 @@
import { Expose, Type } from 'class-transformer'; import { Expose, Type } from 'class-transformer';
import { UsuariosOutputDto } from '../../../usuario/dto/output/usuarios.dto'; import { UsuarioInstitucionCarreraMinOutputDto } from '../../../institucion-usuario/dto/output/usuario-institucion-carrera-min.dto';
export class PrestamoEquipoMinOutputDto { export class PrestamoEquipoMinOutputDto {
@Expose() @Expose()
@@ -18,6 +18,6 @@ export class PrestamoEquipoMinOutputDto {
hora_inicio; hora_inicio;
@Expose() @Expose()
@Type(() => UsuariosOutputDto) @Type(() => UsuarioInstitucionCarreraMinOutputDto)
usuario; institucionUsuario;
} }
@@ -1,6 +1,6 @@
import { Expose, Type } from 'class-transformer'; import { Expose, Type } from 'class-transformer';
import { EquipoMinOutputDto } from '../../../equipo/dto/output/equipo-min.dto'; import { EquipoMinOutputDto } from '../../../equipo/dto/output/equipo-min.dto';
import { UsuariosOutputDto } from '../../../usuario/dto/output/usuarios.dto'; import { UsuarioInstitucionCarreraMinOutputDto } from '../../../institucion-usuario/dto/output/usuario-institucion-carrera-min.dto';
export class PrestamoEquipoOutputDto { export class PrestamoEquipoOutputDto {
@Expose() @Expose()
@@ -29,6 +29,6 @@ export class PrestamoEquipoOutputDto {
equipo; equipo;
@Expose() @Expose()
@Type(() => UsuariosOutputDto) @Type(() => UsuarioInstitucionCarreraMinOutputDto)
usuario; institucionUsuario;
} }
+3 -3
View File
@@ -1,6 +1,6 @@
import { Expose, Type } from 'class-transformer'; import { Expose, Type } from 'class-transformer';
import { EquipoMinOutputDto } from '../../../equipo/dto/output/equipo-min.dto'; import { EquipoMinOutputDto } from '../../../equipo/dto/output/equipo-min.dto';
import { UsuariosOutputDto } from '../../../usuario/dto/output/usuarios.dto'; import { UsuarioInstitucionCarreraMinOutputDto } from '../../../institucion-usuario/dto/output/usuario-institucion-carrera-min.dto';
export class PrestamoMinOutputDto { export class PrestamoMinOutputDto {
@Expose() @Expose()
@@ -20,6 +20,6 @@ export class PrestamoMinOutputDto {
equipo; equipo;
@Expose() @Expose()
@Type(() => UsuariosOutputDto) @Type(() => UsuarioInstitucionCarreraMinOutputDto)
usuario; institucionUsuario;
} }
+3
View File
@@ -11,6 +11,9 @@ export class PrestamoOutputDto {
@Expose() @Expose()
fecha_inicio; fecha_inicio;
@Expose()
hora_server;
@Expose() @Expose()
hora_fin; hora_fin;
@@ -1,6 +1,6 @@
import { Expose, Type } from 'class-transformer'; import { Expose, Type } from 'class-transformer';
import { OperadorMinOutputDto } from '../../../operador/dto/output/operador-min.dto'; import { OperadorMinOutputDto } from '../../../operador/dto/output/operador-min.dto';
import { UsuariosOutputDto } from '../../../usuario/dto/output/usuarios.dto'; import { UsuarioInstitucionCarreraMinOutputDto } from '../../../institucion-usuario/dto/output/usuario-institucion-carrera-min.dto';
export class PrestamosEquipoOutputDto { export class PrestamosEquipoOutputDto {
@Expose() @Expose()
@@ -39,6 +39,6 @@ export class PrestamosEquipoOutputDto {
operadorRegreso; operadorRegreso;
@Expose() @Expose()
@Type(() => UsuariosOutputDto) @Type(() => UsuarioInstitucionCarreraMinOutputDto)
usuario; institucionUsuario;
} }
+3 -3
View File
@@ -1,7 +1,7 @@
import { Expose, Type } from 'class-transformer'; import { Expose, Type } from 'class-transformer';
import { EquipoMinOutputDto } from '../../../equipo/dto/output/equipo-min.dto'; import { EquipoMinOutputDto } from '../../../equipo/dto/output/equipo-min.dto';
import { OperadorMinOutputDto } from '../../../operador/dto/output/operador-min.dto'; import { OperadorMinOutputDto } from '../../../operador/dto/output/operador-min.dto';
import { UsuariosOutputDto } from '../../../usuario/dto/output/usuarios.dto'; import { UsuarioInstitucionCarreraMinOutputDto } from '../../../institucion-usuario/dto/output/usuario-institucion-carrera-min.dto';
export class PrestamosOutputDto { export class PrestamosOutputDto {
@Expose() @Expose()
@@ -44,6 +44,6 @@ export class PrestamosOutputDto {
operadorRegreso; operadorRegreso;
@Expose() @Expose()
@Type(() => UsuariosOutputDto) @Type(() => UsuarioInstitucionCarreraMinOutputDto)
usuario; institucionUsuario;
} }
+40 -31
View File
@@ -2,95 +2,104 @@ import { Expose } from 'class-transformer';
export class ReporteOutputDto { export class ReporteOutputDto {
@Expose() @Expose()
id_prestamo: number; id_prestamo;
@Expose() @Expose()
activo: number; activo;
@Expose() @Expose()
carrera: string; cancelado_operador;
@Expose() @Expose()
cancelado_operador: number; cancelado_usuario;
@Expose() @Expose()
cancelado_usuario: number; carrera;
@Expose() @Expose()
carrito: string; carrito;
@Expose() @Expose()
equipo: string; equipo;
@Expose() @Expose()
fecha_entrega: Date; fecha_entrega;
@Expose() @Expose()
fecha_inicio: Date; fecha_inicio;
@Expose() @Expose()
hora_fin: Date; hora_fin;
@Expose() @Expose()
hora_inicio: Date; hora_inicio;
@Expose() @Expose()
hora_max_recoger: Date; hora_max_recoger;
@Expose() @Expose()
id_carrito: number; id_carrera;
@Expose() @Expose()
id_equipo: number; id_carrito;
@Expose() @Expose()
id_institucion: number; id_equipo;
@Expose() @Expose()
id_institucion_carrera: number; id_institucion;
@Expose() @Expose()
id_modulo: number; id_institucion_carrera;
@Expose() @Expose()
id_operador_entrega: number; id_institucion_usuario;
@Expose() @Expose()
id_operador_regreso: number; id_modulo;
@Expose() @Expose()
id_status: number; id_operador_entrega;
@Expose() @Expose()
id_tipo_carrito: number; id_operador_regreso;
@Expose() @Expose()
id_tipo_usuario: number; id_status;
@Expose() @Expose()
id_usuario: number; id_tipo_carrito;
@Expose() @Expose()
institucion: string; id_tipo_usuario;
@Expose() @Expose()
modulo: string; id_usuario;
@Expose() @Expose()
nombre: string; institucion;
@Expose() @Expose()
numero_inventario: string; modulo;
@Expose() @Expose()
operador_entrega: string; nombre;
@Expose() @Expose()
operador_regreso: string; numero_inventario;
@Expose() @Expose()
tipo_carrito: string; operador_entrega;
@Expose() @Expose()
usuario: string; operador_regreso;
@Expose()
tipo_carrito;
@Expose()
tipo_usuario;
@Expose()
usuario;
} }
+9 -17
View File
@@ -10,7 +10,6 @@ import { Equipo } from '../../equipo/entity/equipo.entity';
import { InstitucionUsuario } from '../../institucion-usuario/entity/institucion-usuario.entity'; import { InstitucionUsuario } from '../../institucion-usuario/entity/institucion-usuario.entity';
import { Multa } from '../../multa/entity/multa.entity'; import { Multa } from '../../multa/entity/multa.entity';
import { Operador } from '../../operador/entity/operador.entity'; import { Operador } from '../../operador/entity/operador.entity';
import { Usuario } from '../../usuario/entity/usuario.entity';
@Entity() @Entity()
export class Prestamo { export class Prestamo {
@@ -47,8 +46,8 @@ export class Prestamo {
@Column({ type: Number, nullable: true }) @Column({ type: Number, nullable: true })
id_equipo: number; id_equipo: number;
// @Column({ type: Number, nullable: true }) @Column({ type: Number, nullable: true })
// id_institucion_usuario: number; id_institucion_usuario: number;
@Column({ type: Number, nullable: true, default: 1 }) @Column({ type: Number, nullable: true, default: 1 })
id_operador_entrega: number; id_operador_entrega: number;
@@ -56,20 +55,17 @@ export class Prestamo {
@Column({ type: Number, nullable: true, default: 1 }) @Column({ type: Number, nullable: true, default: 1 })
id_operador_regreso: number; id_operador_regreso: number;
@Column({ type: Number, nullable: true })
id_usuario: number;
@ManyToOne(() => Equipo, (equipo) => equipo.prestamos, { eager: true }) @ManyToOne(() => Equipo, (equipo) => equipo.prestamos, { eager: true })
@JoinColumn({ name: 'id_equipo' }) @JoinColumn({ name: 'id_equipo' })
equipo: Equipo; equipo: Equipo;
// @ManyToOne( @ManyToOne(
// () => InstitucionUsuario, () => InstitucionUsuario,
// (institucionUsuario) => institucionUsuario.prestamos, (institucionUsuario) => institucionUsuario.prestamos,
// { eager: true }, { eager: true },
// ) )
// @JoinColumn({ name: 'id_institucion_usuario' }) @JoinColumn({ name: 'id_institucion_usuario' })
// institucionUsuario: InstitucionUsuario; institucionUsuario: InstitucionUsuario;
@ManyToOne( @ManyToOne(
() => Operador, () => Operador,
@@ -87,10 +83,6 @@ export class Prestamo {
@JoinColumn({ name: 'id_operador_regreso' }) @JoinColumn({ name: 'id_operador_regreso' })
operadorRegreso: Operador; operadorRegreso: Operador;
@ManyToOne(() => Usuario, (usuario) => usuario.prestamos, { eager: true })
@JoinColumn({ name: 'id_usuario' })
usuario: Usuario;
@OneToMany(() => Multa, (multa) => multa.prestamo) @OneToMany(() => Multa, (multa) => multa.prestamo)
multa: Multa; multa: Multa;
} }
@@ -8,6 +8,7 @@ import { Modulo } from '../../../modulo/entity/modulo.entity';
import { Operador } from '../../../operador/entity/operador.entity'; import { Operador } from '../../../operador/entity/operador.entity';
import { Prestamo } from '../prestamo.entity'; import { Prestamo } from '../prestamo.entity';
import { TipoCarrito } from '../../../institucion-tipo-carrito/entity/tipo-carrito.entity'; import { TipoCarrito } from '../../../institucion-tipo-carrito/entity/tipo-carrito.entity';
import { TipoUsuario } from '../../../tipo-usuario/entity/tipo-usuario.entity';
import { Usuario } from '../../../usuario/entity/usuario.entity'; import { Usuario } from '../../../usuario/entity/usuario.entity';
import { Carrera } from '../../../institucion-carrera/entity/carrera.entity'; import { Carrera } from '../../../institucion-carrera/entity/carrera.entity';
@@ -25,45 +26,53 @@ import { Carrera } from '../../../institucion-carrera/entity/carrera.entity';
.addSelect('p.hora_inicio', 'hora_inicio') .addSelect('p.hora_inicio', 'hora_inicio')
.addSelect('p.hora_max_recoger', 'hora_max_recoger') .addSelect('p.hora_max_recoger', 'hora_max_recoger')
.addSelect('p.id_equipo', 'id_equipo') .addSelect('p.id_equipo', 'id_equipo')
.addSelect('p.id_usuario', 'id_usuario') .addSelect('p.id_institucion_usuario', 'id_institucion_usuario')
.addSelect('p.id_operador_entrega', 'id_operador_entrega') .addSelect('p.id_operador_entrega', 'id_operador_entrega')
.addSelect('p.id_operador_regreso', 'id_operador_regreso') .addSelect('p.id_operador_regreso', 'id_operador_regreso')
.addSelect('e.equipo', 'equipo') .addSelect('e.equipo', 'equipo')
.addSelect('e.id_carrito', 'id_carrito') .addSelect('e.id_carrito', 'id_carrito')
.addSelect('e.id_status', 'id_status') .addSelect('e.id_status', 'id_status')
.addSelect('e.numero_inventario', 'numero_inventario') .addSelect('e.numero_inventario', 'numero_inventario')
.addSelect('iu.id_institucion_carrera', 'id_institucion_carrera')
.addSelect('iu.id_usuario', 'id_usuario')
.addSelect('oe.operador', 'operador_entrega') .addSelect('oe.operador', 'operador_entrega')
.addSelect('or.operador', 'operador_regreso') .addSelect('or.operador', 'operador_regreso')
.addSelect('u.id_tipo_usuario', 'id_tipo_usuario')
.addSelect('u.nombre', 'nombre')
.addSelect('u.usuario', 'usuario')
.addSelect('c.carrito', 'carrito') .addSelect('c.carrito', 'carrito')
.addSelect('c.id_modulo', 'id_modulo') .addSelect('c.id_modulo', 'id_modulo')
.addSelect('c.id_tipo_carrito', 'id_tipo_carrito') .addSelect('c.id_tipo_carrito', 'id_tipo_carrito')
.addSelect('ic.id_carrera', 'id_carrera')
.addSelect('u.id_tipo_usuario', 'id_tipo_usuario')
.addSelect('u.nombre', 'nombre')
.addSelect('u.usuario', 'usuario')
.addSelect('m.id_institucion', 'id_institucion') .addSelect('m.id_institucion', 'id_institucion')
.addSelect('m.modulo', 'modulo') .addSelect('m.modulo', 'modulo')
.addSelect('tu.tipo_usuario', 'tipo_usuario')
.addSelect('tc.tipo_carrito', 'tipo_carrito') .addSelect('tc.tipo_carrito', 'tipo_carrito')
.addSelect('i.institucion', 'institucion') .addSelect('i.institucion', 'institucion')
.addSelect('ca.carrera', 'carrera') .addSelect('ca.carrera', 'carrera')
.addSelect('ic.id_institucion_carrera', 'id_institucion_carrera')
.from(Prestamo, 'p') .from(Prestamo, 'p')
.innerJoin(Equipo, 'e', 'e.id_equipo = p.id_equipo') .innerJoin(Equipo, 'e', 'e.id_equipo = p.id_equipo')
.innerJoin(Operador, 'oe', 'oe.id_operador = p.id_operador_regreso') .innerJoin(
.innerJoin(Operador, 'or', 'or.id_operador = p.id_operador_entrega') InstitucionUsuario,
.innerJoin(Usuario, 'u', 'u.id_usuario = p.id_usuario') 'iu',
'iu.id_institucion_usuario = p.id_institucion_usuario',
)
.innerJoin(Operador, 'oe', 'oe.id_operador = p.id_operador_entrega')
.innerJoin(Operador, 'or', 'or.id_operador = p.id_operador_regreso')
.innerJoin(Carrito, 'c', 'c.id_carrito = e.id_carrito') .innerJoin(Carrito, 'c', 'c.id_carrito = e.id_carrito')
.innerJoin(InstitucionUsuario, 'iu', 'iu.id_usuario = u.id_usuario')
.innerJoin( .innerJoin(
InstitucionCarrera, InstitucionCarrera,
'ic', 'ic',
'ic.id_institucion_carrera = iu.id_institucion_carrera', 'ic.id_institucion_carrera = iu.id_institucion_carrera',
) )
.innerJoin(Usuario, 'u', 'u.id_usuario = iu.id_usuario')
.innerJoin(Modulo, 'm', 'm.id_modulo = c.id_modulo') .innerJoin(Modulo, 'm', 'm.id_modulo = c.id_modulo')
.innerJoin(TipoUsuario, 'tu', 'tu.id_tipo_usuario = u.id_tipo_usuario')
.innerJoin(TipoCarrito, 'tc', 'tc.id_tipo_carrito = c.id_tipo_carrito') .innerJoin(TipoCarrito, 'tc', 'tc.id_tipo_carrito = c.id_tipo_carrito')
.innerJoin(Institucion, 'i', 'i.id_institucion = m.id_institucion') .innerJoin(Institucion, 'i', 'i.id_institucion = m.id_institucion')
.innerJoin(Carrera, 'ca', 'ca.id_carrera = ic.id_carrera') .innerJoin(Carrera, 'ca', 'ca.id_carrera = ic.id_carrera')
.where('i.id_institucion = ic.id_institucion') .orderBy('i.institucion')
.orderBy('i.institucion'), .addOrderBy('p.id_prestamo'),
}) })
export class FullInformacionPrestamoView { export class FullInformacionPrestamoView {
@ViewColumn() @ViewColumn()
@@ -72,15 +81,15 @@ export class FullInformacionPrestamoView {
@ViewColumn() @ViewColumn()
activo: number; activo: number;
@ViewColumn()
carrera: string;
@ViewColumn() @ViewColumn()
cancelado_operador: number; cancelado_operador: number;
@ViewColumn() @ViewColumn()
cancelado_usuario: number; cancelado_usuario: number;
@ViewColumn()
carrera: string;
@ViewColumn() @ViewColumn()
carrito: string; carrito: string;
@@ -102,6 +111,9 @@ export class FullInformacionPrestamoView {
@ViewColumn() @ViewColumn()
hora_max_recoger: Date; hora_max_recoger: Date;
@ViewColumn()
id_carrera: number;
@ViewColumn() @ViewColumn()
id_carrito: number; id_carrito: number;
@@ -114,6 +126,9 @@ export class FullInformacionPrestamoView {
@ViewColumn() @ViewColumn()
id_institucion_carrera: number; id_institucion_carrera: number;
@ViewColumn()
id_institucion_usuario: number;
@ViewColumn() @ViewColumn()
id_modulo: number; id_modulo: number;
@@ -156,6 +171,9 @@ export class FullInformacionPrestamoView {
@ViewColumn() @ViewColumn()
tipo_carrito: string; tipo_carrito: string;
@ViewColumn()
tipo_usuario: string;
@ViewColumn() @ViewColumn()
usuario: string; usuario: string;
} }
@@ -1,8 +1,9 @@
import { DataSource, ViewEntity, ViewColumn } from 'typeorm'; import { DataSource, ViewEntity, ViewColumn } from 'typeorm';
import { Carrito } from '../../../carrito/entity/carrito.entity'; import { Carrito } from '../../../carrito/entity/carrito.entity';
import { Prestamo } from '../prestamo.entity';
import { Equipo } from '../../../equipo/entity/equipo.entity'; import { Equipo } from '../../../equipo/entity/equipo.entity';
import { InstitucionUsuario } from '../../../institucion-usuario/entity/institucion-usuario.entity';
import { Modulo } from '../../../modulo/entity/modulo.entity'; import { Modulo } from '../../../modulo/entity/modulo.entity';
import { Prestamo } from '../prestamo.entity';
import { Status } from '../../../status/entity/status.entity'; import { Status } from '../../../status/entity/status.entity';
import { TipoCarrito } from '../../../institucion-tipo-carrito/entity/tipo-carrito.entity'; import { TipoCarrito } from '../../../institucion-tipo-carrito/entity/tipo-carrito.entity';
@@ -20,14 +21,16 @@ import { TipoCarrito } from '../../../institucion-tipo-carrito/entity/tipo-carri
.addSelect('p.hora_inicio', 'hora_inicio') .addSelect('p.hora_inicio', 'hora_inicio')
.addSelect('p.hora_max_recoger', 'hora_max_recoger') .addSelect('p.hora_max_recoger', 'hora_max_recoger')
.addSelect('p.id_equipo', 'id_equipo') .addSelect('p.id_equipo', 'id_equipo')
.addSelect('p.id_institucion_usuario', 'id_institucion_usuario')
.addSelect('p.id_operador_entrega', 'id_operador_entrega') .addSelect('p.id_operador_entrega', 'id_operador_entrega')
.addSelect('p.id_operador_regreso', 'id_operador_regreso') .addSelect('p.id_operador_regreso', 'id_operador_regreso')
.addSelect('p.id_usuario', 'id_usuario')
.addSelect('e.equipo', 'equipo') .addSelect('e.equipo', 'equipo')
.addSelect('e.u', 'u')
.addSelect('e.id_carrito', 'id_carrito') .addSelect('e.id_carrito', 'id_carrito')
.addSelect('e.id_status', 'id_status') .addSelect('e.id_status', 'id_status')
.addSelect('e.numero_inventario', 'numero_inventario') .addSelect('e.numero_inventario', 'numero_inventario')
.addSelect('e.u', 'u')
.addSelect('iu.id_institucion_carrera', 'id_institucion_carrera')
.addSelect('iu.id_usuario', 'id_usuario')
.addSelect('c.carrito', 'carrito') .addSelect('c.carrito', 'carrito')
.addSelect('c.id_modulo', 'id_modulo') .addSelect('c.id_modulo', 'id_modulo')
.addSelect('c.id_tipo_carrito', 'id_tipo_carrito') .addSelect('c.id_tipo_carrito', 'id_tipo_carrito')
@@ -35,6 +38,11 @@ import { TipoCarrito } from '../../../institucion-tipo-carrito/entity/tipo-carri
.addSelect('tc.tipo_carrito', 'tipo_carrito') .addSelect('tc.tipo_carrito', 'tipo_carrito')
.from(Prestamo, 'p') .from(Prestamo, 'p')
.innerJoin(Equipo, 'e', 'e.id_equipo = p.id_equipo') .innerJoin(Equipo, 'e', 'e.id_equipo = p.id_equipo')
.innerJoin(
InstitucionUsuario,
'iu',
'iu.id_institucion_usuario = p.id_institucion_usuario',
)
.innerJoin(Carrito, 'c', 'c.id_carrito = e.id_carrito') .innerJoin(Carrito, 'c', 'c.id_carrito = e.id_carrito')
.innerJoin(Status, 's', 's.id_status = e.id_status') .innerJoin(Status, 's', 's.id_status = e.id_status')
.innerJoin(Modulo, 'm', 'm.id_modulo = c.id_modulo') .innerJoin(Modulo, 'm', 'm.id_modulo = c.id_modulo')
@@ -83,6 +91,12 @@ export class InformacionPrestamoView {
@ViewColumn() @ViewColumn()
id_institucion: number; id_institucion: number;
@ViewColumn()
id_institucion_carrera: number;
@ViewColumn()
id_institucion_usuario: number;
@ViewColumn() @ViewColumn()
id_modulo: number; id_modulo: number;
@@ -2,6 +2,7 @@ import { DataSource, ViewEntity, ViewColumn } from 'typeorm';
import { Carrito } from '../../../carrito/entity/carrito.entity'; import { Carrito } from '../../../carrito/entity/carrito.entity';
import { Equipo } from '../../../equipo/entity/equipo.entity'; import { Equipo } from '../../../equipo/entity/equipo.entity';
import { Institucion } from '../../../institucion/entity/institucion.entity'; import { Institucion } from '../../../institucion/entity/institucion.entity';
import { InstitucionUsuario } from '../../../institucion-usuario/entity/institucion-usuario.entity';
import { Modulo } from '../../../modulo/entity/modulo.entity'; import { Modulo } from '../../../modulo/entity/modulo.entity';
import { Prestamo } from '../prestamo.entity'; import { Prestamo } from '../prestamo.entity';
import { TipoCarrito } from '../../../institucion-tipo-carrito/entity/tipo-carrito.entity'; import { TipoCarrito } from '../../../institucion-tipo-carrito/entity/tipo-carrito.entity';
@@ -21,26 +22,33 @@ import { Usuario } from '../../../usuario/entity/usuario.entity';
.addSelect('p.hora_inicio', 'hora_inicio') .addSelect('p.hora_inicio', 'hora_inicio')
.addSelect('p.hora_max_recoger', 'hora_max_recoger') .addSelect('p.hora_max_recoger', 'hora_max_recoger')
.addSelect('p.id_equipo', 'id_equipo') .addSelect('p.id_equipo', 'id_equipo')
.addSelect('p.id_usuario', 'id_usuario') .addSelect('p.id_institucion_usuario', 'id_institucion_usuario')
.addSelect('e.equipo', 'equipo') .addSelect('e.equipo', 'equipo')
.addSelect('e.u', 'u') .addSelect('e.u', 'u')
.addSelect('e.id_carrito', 'id_carrito') .addSelect('e.id_carrito', 'id_carrito')
.addSelect('e.id_status', 'id_status') .addSelect('e.id_status', 'id_status')
.addSelect('e.numero_inventario', 'numero_inventario') .addSelect('e.numero_inventario', 'numero_inventario')
.addSelect('u.id_tipo_usuario', 'id_tipo_usuario') .addSelect('iu.id_institucion_carrera', 'id_institucion_carrera')
.addSelect('u.nombre', 'nombre') .addSelect('iu.id_usuario', 'id_usuario')
.addSelect('u.usuario', 'usuario')
.addSelect('c.carrito', 'carrito') .addSelect('c.carrito', 'carrito')
.addSelect('c.id_modulo', 'id_modulo') .addSelect('c.id_modulo', 'id_modulo')
.addSelect('c.id_tipo_carrito', 'id_tipo_carrito') .addSelect('c.id_tipo_carrito', 'id_tipo_carrito')
.addSelect('u.id_tipo_usuario', 'id_tipo_usuario')
.addSelect('u.nombre', 'nombre')
.addSelect('u.usuario', 'usuario')
.addSelect('m.id_institucion', 'id_institucion') .addSelect('m.id_institucion', 'id_institucion')
.addSelect('m.modulo', 'modulo') .addSelect('m.modulo', 'modulo')
.addSelect('tc.tipo_carrito', 'tipo_carrito') .addSelect('tc.tipo_carrito', 'tipo_carrito')
.addSelect('i.institucion', 'institucion') .addSelect('i.institucion', 'institucion')
.from(Prestamo, 'p') .from(Prestamo, 'p')
.innerJoin(Equipo, 'e', 'e.id_equipo = p.id_equipo') .innerJoin(Equipo, 'e', 'e.id_equipo = p.id_equipo')
.innerJoin(Usuario, 'u', 'u.id_usuario = p.id_usuario') .innerJoin(
InstitucionUsuario,
'iu',
'iu.id_institucion_usuario = p.id_institucion_usuario',
)
.innerJoin(Carrito, 'c', 'c.id_carrito = e.id_carrito') .innerJoin(Carrito, 'c', 'c.id_carrito = e.id_carrito')
.innerJoin(Usuario, 'u', 'u.id_usuario = iu.id_usuario')
.innerJoin(Modulo, 'm', 'm.id_modulo = c.id_modulo') .innerJoin(Modulo, 'm', 'm.id_modulo = c.id_modulo')
.innerJoin(TipoCarrito, 'tc', 'tc.id_tipo_carrito = c.id_tipo_carrito') .innerJoin(TipoCarrito, 'tc', 'tc.id_tipo_carrito = c.id_tipo_carrito')
.innerJoin(Institucion, 'i', 'i.id_institucion = m.id_institucion'), .innerJoin(Institucion, 'i', 'i.id_institucion = m.id_institucion'),
@@ -88,6 +96,12 @@ export class PrestamoInformacionView {
@ViewColumn() @ViewColumn()
id_institucion: number; id_institucion: number;
@ViewColumn()
id_institucion_carrera: number;
@ViewColumn()
id_institucion_usuario: number;
@ViewColumn() @ViewColumn()
id_modulo: number; id_modulo: number;
+58 -10
View File
@@ -1,3 +1,4 @@
import * as moment from 'moment';
import { import {
Body, Body,
Controller, Controller,
@@ -8,6 +9,7 @@ import {
Request, Request,
UseGuards, UseGuards,
} from '@nestjs/common'; } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { AuthGuard } from '@nestjs/passport'; import { AuthGuard } from '@nestjs/passport';
import { import {
ApiBearerAuth, ApiBearerAuth,
@@ -47,10 +49,15 @@ import { ReporteOutputDto } from './dto/output/reporte';
@Controller('prestamo') @Controller('prestamo')
@ApiTags('prestamo') @ApiTags('prestamo')
export class PrestamoController { export class PrestamoController {
private add: number;
constructor( constructor(
private configService: ConfigService,
private prestamoService: PrestamoService, private prestamoService: PrestamoService,
private validarUsuarioService: ValidarUsuarioService, private validarUsuarioService: ValidarUsuarioService,
) {} ) {
this.add = parseInt(this.configService.get<string>('ADD_HORA'));
}
@Serealize(ActivosOutputDto) @Serealize(ActivosOutputDto)
@Get('activos') @Get('activos')
@@ -359,6 +366,7 @@ export class PrestamoController {
ejemplo: { ejemplo: {
value: { value: {
id_modulo: 1, id_modulo: 1,
id_institucion_usuario: 1,
id_tipo_carrito: 1, id_tipo_carrito: 1,
_id_programa: 1, _id_programa: 1,
_id_tipo_entrada: 1, _id_tipo_entrada: 1,
@@ -370,13 +378,27 @@ export class PrestamoController {
const usuario: Usuario = req.user.usuario; const usuario: Usuario = req.user.usuario;
this.validarUsuarioService.validarUsuario(usuario); this.validarUsuarioService.validarUsuario(usuario);
return this.prestamoService.create( return this.prestamoService
usuario, .create(
body.id_modulo, usuario,
body.id_tipo_carrito, body.id_institucion_usuario,
body.id_programa, body.id_modulo,
body.id_tipo_entrada, body.id_tipo_carrito,
); body.id_programa,
body.id_tipo_entrada,
)
.then((prestamo) => {
if (prestamo) {
const ahora = moment();
if (this.add) ahora.add(this.add, 'h');
const hora_server = { hora_server: ahora.format() };
Object.assign(prestamo, hora_server);
}
return prestamo;
});
} }
@Serealize(PrestamoOutputDto) @Serealize(PrestamoOutputDto)
@@ -396,7 +418,20 @@ export class PrestamoController {
if (usuarioOperador instanceof Usuario) if (usuarioOperador instanceof Usuario)
this.validarUsuarioService.validarUsuario(usuarioOperador); this.validarUsuarioService.validarUsuario(usuarioOperador);
else this.validarUsuarioService.validarSoloOperador(usuarioOperador); else this.validarUsuarioService.validarSoloOperador(usuarioOperador);
return this.prestamoService.prestamoInfoById(parseInt(query.id_prestamo)); return this.prestamoService
.prestamoInfoById(parseInt(query.id_prestamo))
.then((prestamo) => {
if (prestamo) {
const ahora = moment();
if (this.add) ahora.add(this.add, 'h');
const hora_server = { hora_server: ahora.format() };
Object.assign(prestamo, hora_server);
}
return prestamo;
});
} }
@Serealize(PrestamoOutputDto) @Serealize(PrestamoOutputDto)
@@ -410,7 +445,20 @@ export class PrestamoController {
const usuario: Usuario = req.user.usuario; const usuario: Usuario = req.user.usuario;
this.validarUsuarioService.validarUsuario(usuario); this.validarUsuarioService.validarUsuario(usuario);
return this.prestamoService.prestamoInfoByUsuario(usuario, false); return this.prestamoService
.prestamoInfoByUsuario(usuario, false)
.then((prestamo) => {
if (prestamo) {
const ahora = moment();
if (this.add) ahora.add(this.add, 'h');
const hora_server = { hora_server: ahora.format() };
Object.assign(prestamo, hora_server);
}
return prestamo;
});
} }
@Serealize(PrestamoEquipoOutputDto) @Serealize(PrestamoEquipoOutputDto)
+140 -87
View File
@@ -1,6 +1,5 @@
import * as moment from 'moment'; import * as moment from 'moment';
import { import {
BadRequestException,
ConflictException, ConflictException,
ForbiddenException, ForbiddenException,
forwardRef, forwardRef,
@@ -8,6 +7,7 @@ import {
Injectable, Injectable,
NotFoundException, NotFoundException,
} from '@nestjs/common'; } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { InjectRepository } from '@nestjs/typeorm'; import { InjectRepository } from '@nestjs/typeorm';
import { import {
Between, Between,
@@ -20,7 +20,6 @@ import {
} from 'typeorm'; } from 'typeorm';
import { AppGateway } from '../app.gateway'; import { AppGateway } from '../app.gateway';
import { Institucion } from '../institucion/entity/institucion.entity'; import { Institucion } from '../institucion/entity/institucion.entity';
import { InstitucionUsuario } from '../institucion-usuario/entity/institucion-usuario.entity';
import { Modulo } from '../modulo/entity/modulo.entity'; import { Modulo } from '../modulo/entity/modulo.entity';
import { Operador } from '../operador/entity/operador.entity'; import { Operador } from '../operador/entity/operador.entity';
import { Prestamo } from './entity/prestamo.entity'; import { Prestamo } from './entity/prestamo.entity';
@@ -46,6 +45,8 @@ import { UsuarioService } from '../usuario/usuario.service';
@Injectable() @Injectable()
export class PrestamoService { export class PrestamoService {
private add: number;
constructor( constructor(
@InjectRepository(Prestamo) private repository: Repository<Prestamo>, @InjectRepository(Prestamo) private repository: Repository<Prestamo>,
@InjectRepository(InformacionPrestamoView) @InjectRepository(InformacionPrestamoView)
@@ -55,6 +56,7 @@ export class PrestamoService {
@InjectRepository(PrestamoInformacionView) @InjectRepository(PrestamoInformacionView)
private prestamoInformacionView: Repository<PrestamoInformacionView>, private prestamoInformacionView: Repository<PrestamoInformacionView>,
private appGateway: AppGateway, private appGateway: AppGateway,
private configService: ConfigService,
private equipoService: EquipoService, private equipoService: EquipoService,
private institucionService: InstitucionService, private institucionService: InstitucionService,
private institucionDiaService: InstitucionDiaService, private institucionDiaService: InstitucionDiaService,
@@ -71,7 +73,9 @@ export class PrestamoService {
private statusService: StatusService, private statusService: StatusService,
private tipoUsuarioService: TipoUsuarioService, private tipoUsuarioService: TipoUsuarioService,
private usuarioService: UsuarioService, private usuarioService: UsuarioService,
) {} ) {
this.add = parseInt(this.configService.get<string>('ADD_HORA'));
}
async cancelarOperador( async cancelarOperador(
operadorRegreso: Operador, operadorRegreso: Operador,
@@ -82,6 +86,7 @@ export class PrestamoService {
const ahora = moment(); const ahora = moment();
const prestamo = await this.findById(id_prestamo); const prestamo = await this.findById(id_prestamo);
if (this.add) ahora.add(this.add, 'h');
this.validacionBasicaPrestamo(prestamo); this.validacionBasicaPrestamo(prestamo);
this.validacionOperadorPrestamo(prestamo, operadorRegreso, modulo); this.validacionOperadorPrestamo(prestamo, operadorRegreso, modulo);
// Desactivamos el préstamo // Desactivamos el préstamo
@@ -90,7 +95,7 @@ export class PrestamoService {
prestamo.cancelado_operador = true; prestamo.cancelado_operador = true;
prestamo.operadorRegreso = operadorRegreso; prestamo.operadorRegreso = operadorRegreso;
// Validamos que el equipo si se la haya asignado al usuario del registro // Validamos que el equipo si se la haya asignado al usuario del registro
if (prestamo.equipo.u === prestamo.usuario.id_usuario) { if (prestamo.equipo.u === prestamo.institucionUsuario.usuario.id_usuario) {
// Reseteamos datos del equipo // Reseteamos datos del equipo
prestamo.equipo.u = null; prestamo.equipo.u = null;
prestamo.equipo.status.id_status = 6; prestamo.equipo.status.id_status = 6;
@@ -104,7 +109,9 @@ export class PrestamoService {
// Guardamos cambios en el préstamo // Guardamos cambios en el préstamo
return this.repository.save(prestamo).then((_) => { return this.repository.save(prestamo).then((_) => {
// Actualizamos la interfaz del usaurio // Actualizamos la interfaz del usaurio
this.appGateway.actualizarUsuario(prestamo.usuario.id_usuario); this.appGateway.actualizarUsuario(
prestamo.institucionUsuario.usuario.id_usuario,
);
return { message: 'Se canceló correctamente este préstamo.' }; return { message: 'Se canceló correctamente este préstamo.' };
}); });
} }
@@ -113,6 +120,7 @@ export class PrestamoService {
const ahora = moment(); const ahora = moment();
const prestamo = await this.prestamoInfoByUsuario(usuario); const prestamo = await this.prestamoInfoByUsuario(usuario);
if (this.add) ahora.add(this.add, 'h');
this.validacionBasicaPrestamo(prestamo); this.validacionBasicaPrestamo(prestamo);
// Desactivamos el préstamo // Desactivamos el préstamo
prestamo.activo = false; prestamo.activo = false;
@@ -148,18 +156,25 @@ export class PrestamoService {
async create( async create(
usuario: Usuario, usuario: Usuario,
id_institucion_usuario: number,
id_modulo: number, id_modulo: number,
id_tipo_carrito: number, id_tipo_carrito: number,
id_programa?: number, id_programa?: number,
id_tipo_entrada?: number, id_tipo_entrada?: number,
): Promise<Prestamo> { ): Promise<Prestamo> {
const ahora = moment(); const ahora = moment();
if (this.add) ahora.add(this.add, 'h');
const ahoraStr = ahora.format('YYYY-MM-DD'); const ahoraStr = ahora.format('YYYY-MM-DD');
const modulo = await this.moduloService.findFullInfoById(id_modulo); const modulo = await this.moduloService.findFullInfoById(id_modulo);
const tipoCarrito = const tipoCarrito =
await this.institucionTipoCarritoService.findTipoCarritoById( await this.institucionTipoCarritoService.findTipoCarritoById(
id_tipo_carrito, id_tipo_carrito,
); );
const institucionUsuario = await this.institucionUsuarioService.findById(
id_institucion_usuario,
);
const institucionDia = await this.institucionDiaService.hoy( const institucionDia = await this.institucionDiaService.hoy(
modulo.institucion, modulo.institucion,
); );
@@ -178,6 +193,19 @@ export class PrestamoService {
) )
: null; : null;
// Validamos que el id_institucion_usuario le pertenezca al usuario
if (institucionUsuario.usuario.id_usuario != usuario.id_usuario)
throw new ConflictException('No te pertenece esta información.');
// Validamos que este activo
if (!institucionUsuario.activo)
throw new ForbiddenException(
`${this.mensajeNoPoderPedir()} tu cuenta esta desactivada en esta institución.`,
);
// Validamos que no tenga multa
if (institucionUsuario.multa)
throw new ForbiddenException(
`${this.mensajeNoPoderPedir()} tienes una multa activa.`,
);
// Validamos si ese día se encuentra activo // Validamos si ese día se encuentra activo
if (!institucionDia.activo) if (!institucionDia.activo)
throw new ConflictException( throw new ConflictException(
@@ -208,21 +236,14 @@ export class PrestamoService {
`Se suspendió el servicio de préstamo temporalmente de ${institucionDia.horasExcepcion[i].hora_inicio} a ${institucionDia.horasExcepcion[i].hora_fin}.`, `Se suspendió el servicio de préstamo temporalmente de ${institucionDia.horasExcepcion[i].hora_inicio} a ${institucionDia.horasExcepcion[i].hora_fin}.`,
); );
} }
// Buscamos las instituciones usuario de este usuario // Buscamos un prestamo activo con el id del usuario que realiza la acción
return this.institucionUsuarioService return this.informacionPrestamoView
.findFullInfoAllByIdUsuario(usuario, false) .findOne({ where: { activo: 1, id_usuario: usuario.id_usuario } })
.then((instituciones) => {
this.validarInstitucionUsuario(instituciones, modulo);
// Buscamos un prestamo activo con el id del usuario que realiza la acción
return this.informacionPrestamoView.findOne({
where: { activo: 1, id_usuario: usuario.id_usuario },
});
})
.then((existePrestamo) => { .then((existePrestamo) => {
// Sacamos error si lo encuentra // Sacamos error si lo encuentra
if (existePrestamo) if (existePrestamo)
throw new ConflictException( throw new ConflictException(
'Este usuario ya tiene un préstamo activo.', `${this.mensajeNoPoderPedir()} ya cuentas con un préstamo activo.`,
); );
// Buscamos un equipo con las caracteríasticas solicitadas // Buscamos un equipo con las caracteríasticas solicitadas
return this.equipoService.findEquipo( return this.equipoService.findEquipo(
@@ -242,7 +263,7 @@ export class PrestamoService {
.add(modulo.institucion.tiempo_recoger, 'm') .add(modulo.institucion.tiempo_recoger, 'm')
.toDate(), .toDate(),
equipo, equipo,
usuario, institucionUsuario,
}), }),
), ),
) )
@@ -252,12 +273,15 @@ export class PrestamoService {
// Si es locker // Si es locker
if ( if (
prestamo.equipo.carrito.tipoCarrito.id_tipo_carrito === 4 || prestamo.equipo.carrito.tipoCarrito.id_tipo_carrito === 4 ||
prestamo.equipo.carrito.tipoCarrito.id_tipo_carrito === 5 prestamo.equipo.carrito.tipoCarrito.id_tipo_carrito === 5||
prestamo.equipo.carrito.tipoCarrito.id_tipo_carrito === 7||
prestamo.equipo.carrito.tipoCarrito.id_tipo_carrito === 8
) )
// Creamos un passcode // Creamos un passcode
return this.passcodeService return this.passcodeService.create(prestamo).then((passcode) => {
.create(prestamo) Object.assign(prestamo, passcode);
.then((passcode) => ({ ...prestamo, passcode: passcode.passcode })); return prestamo;
});
return prestamo; return prestamo;
}); });
} }
@@ -268,6 +292,9 @@ export class PrestamoService {
id_prestamo: number | Prestamo, id_prestamo: number | Prestamo,
): Promise<Equipo> { ): Promise<Equipo> {
const ahora = moment(); const ahora = moment();
if (this.add) ahora.add(this.add, 'h');
const ahoraStr = ahora.format('YYYY-MM-DD'); const ahoraStr = ahora.format('YYYY-MM-DD');
const prestamo = const prestamo =
typeof id_prestamo === 'number' typeof id_prestamo === 'number'
@@ -301,7 +328,7 @@ export class PrestamoService {
throw new ConflictException( throw new ConflictException(
'Hubo un error, comunicate con los desarrolladores.', 'Hubo un error, comunicate con los desarrolladores.',
); );
if (prestamo.usuario.id_usuario != prestamo.equipo.u) if (prestamo.institucionUsuario.usuario.id_usuario != prestamo.equipo.u)
throw new ConflictException( throw new ConflictException(
'Este equipo fue asignado más de una vez y este es el préstamo incorrecto, espere unos segundos y se desactivará este préstamo o tanto el usario como el opeardor pueden cancelarlo manualmente.', 'Este equipo fue asignado más de una vez y este es el préstamo incorrecto, espere unos segundos y se desactivará este préstamo o tanto el usario como el opeardor pueden cancelarlo manualmente.',
); );
@@ -319,7 +346,9 @@ export class PrestamoService {
.then((_) => this.repository.save(prestamo)) // Guardo los cambios del préstamo .then((_) => this.repository.save(prestamo)) // Guardo los cambios del préstamo
.then((_) => { .then((_) => {
// Actualizamos la interfaz del usuario // Actualizamos la interfaz del usuario
this.appGateway.actualizarUsuario(prestamo.usuario.id_usuario); this.appGateway.actualizarUsuario(
prestamo.institucionUsuario.usuario.id_usuario,
);
return prestamo.equipo; return prestamo.equipo;
}); });
} }
@@ -377,12 +406,11 @@ export class PrestamoService {
}; };
const busqueda: FindOptionsWhere<FullInformacionPrestamoView> = {}; const busqueda: FindOptionsWhere<FullInformacionPrestamoView> = {};
if (filtros.activo) { if (typeof filtros.activo === 'boolean') {
if (typeof filtros.activo === 'boolean') { busqueda.activo = filtros.activo ? 1 : 0;
busqueda.activo = filtros.activo ? 1 : 0; options.order = { id_prestamo: 'ASC' };
options.order.id_prestamo = 'ASC'; } else if (typeof filtros.activo === 'string')
} else busqueda.activo = filtros.activo === 'true' ? 1 : 0; busqueda.activo = filtros.activo === 'true' ? 1 : 0;
}
if (filtros.cancelado_operador) if (filtros.cancelado_operador)
busqueda.cancelado_operador = busqueda.cancelado_operador =
filtros.cancelado_operador === 'true' ? 1 : 0; filtros.cancelado_operador === 'true' ? 1 : 0;
@@ -422,25 +450,49 @@ export class PrestamoService {
if (filtros.pagina) { if (filtros.pagina) {
options.take = 25; options.take = 25;
options.skip = (parseInt(filtros.pagina) - 1) * 25; options.skip = (parseInt(filtros.pagina) - 1) * 25;
return this.fullInformacionPrestamoView
.findAndCount(options)
.then((infoPrestamos) => {
const prestamos: Prestamo[] = [];
for (let i = 0; i < infoPrestamos[0].length; i++) const activoTrue =
prestamos.push(this.fullViewToPrestamo(infoPrestamos[0][i])); (typeof filtros.activo === 'boolean' && filtros.activo) ||
return [prestamos, infoPrestamos[1]]; (typeof filtros.activo === 'string' && filtros.activo === 'true');
}); const canUseLightCount =
activoTrue && !filtros.usuario && !filtros.id_tipo_usuario;
if (canUseLightCount) {
const { usuario: _u, id_tipo_usuario: _tu, ...countWhere } =
busqueda;
const [rows, total] = await Promise.all([
this.fullInformacionPrestamoView.find(options),
this.informacionPrestamoView.count({
where: countWhere as FindOptionsWhere<InformacionPrestamoView>,
}),
]);
const prestamos = rows.map((row) => this.fullViewToPrestamo(row));
return [prestamos, total];
}
const infoPrestamos = await this.fullInformacionPrestamoView.findAndCount(
options,
);
const prestamos: Prestamo[] = [];
for (let i = 0; i < infoPrestamos[0].length; i++)
prestamos.push(this.fullViewToPrestamo(infoPrestamos[0][i]));
return [prestamos, infoPrestamos[1]];
} }
options.order = { id_institucion: 'ASC', id_prestamo: 'ASC' };
return this.fullInformacionPrestamoView.find(options); return this.fullInformacionPrestamoView.find(options);
} }
findAllActivosExpirados(): Promise<Prestamo[]> { findAllActivosExpirados(): Promise<Prestamo[]> {
const ahora = moment();
if (this.add) ahora.add(this.add, 'h');
return this.informacionPrestamoView return this.informacionPrestamoView
.find({ .find({
where: { where: {
activo: 1, activo: 1,
hora_max_recoger: LessThanOrEqual(moment().toDate()), hora_max_recoger: LessThanOrEqual(ahora.toDate()),
id_status: 2, id_status: 2,
}, },
}) })
@@ -581,6 +633,24 @@ export class PrestamoService {
}, },
status: { id_status: infoPrestamo.id_status }, status: { id_status: infoPrestamo.id_status },
}, },
institucionUsuario: {
id_institucion_usuario: infoPrestamo.id_institucion_usuario,
institucionCarrera: {
id_institucion_carrera: infoPrestamo.id_institucion_carrera,
carrera: {
id_carrera: infoPrestamo.id_carrera,
carrera: infoPrestamo.carrera,
},
},
usuario: {
id_usuario: infoPrestamo.id_usuario,
nombre: infoPrestamo.nombre,
usuario: infoPrestamo.usuario,
tipoUsuario: {
id_tipo_usuario: infoPrestamo.id_tipo_usuario,
},
},
},
operadorEntrega: { operadorEntrega: {
id_operador: infoPrestamo.id_operador_entrega, id_operador: infoPrestamo.id_operador_entrega,
operador: infoPrestamo.operador_entrega, operador: infoPrestamo.operador_entrega,
@@ -589,14 +659,6 @@ export class PrestamoService {
id_operador: infoPrestamo.id_operador_regreso, id_operador: infoPrestamo.id_operador_regreso,
operador: infoPrestamo.operador_regreso, operador: infoPrestamo.operador_regreso,
}, },
usuario: {
id_usuario: infoPrestamo.id_usuario,
nombre: infoPrestamo.nombre,
usuario: infoPrestamo.usuario,
tipoUsuario: {
id_tipo_usuario: infoPrestamo.id_tipo_usuario,
},
},
}); });
} }
@@ -691,25 +753,34 @@ export class PrestamoService {
}, },
status: { id_status: infoPrestamo.id_status }, status: { id_status: infoPrestamo.id_status },
}, },
usuario: { institucionUsuario: {
id_usuario: infoPrestamo.id_usuario, id_institucion_usuario: infoPrestamo.id_institucion_usuario,
usuario: infoPrestamo.usuario, institucionCarrera: {
nombre: infoPrestamo.nombre, id_institucion_carrera: infoPrestamo.id_institucion_carrera,
tipoUsuario: { id_tipo_usuario: infoPrestamo.id_tipo_usuario }, },
usuario: {
id_usuario: infoPrestamo.id_usuario,
usuario: infoPrestamo.usuario,
nombre: infoPrestamo.nombre,
tipoUsuario: { id_tipo_usuario: infoPrestamo.id_tipo_usuario },
},
}, },
}); });
} }
private prestamoPasscode(prestamo: Prestamo) { private prestamoPasscode(prestamo: Prestamo): Promise<Prestamo> | Prestamo {
// Si es locker // Si es locker
if ( if (
prestamo.equipo.carrito.tipoCarrito.id_tipo_carrito === 4 || prestamo.equipo.carrito.tipoCarrito.id_tipo_carrito === 4 ||
prestamo.equipo.carrito.tipoCarrito.id_tipo_carrito === 5 prestamo.equipo.carrito.tipoCarrito.id_tipo_carrito === 5||
prestamo.equipo.carrito.tipoCarrito.id_tipo_carrito === 7||
prestamo.equipo.carrito.tipoCarrito.id_tipo_carrito === 8
) )
// Buscamos el passcode y se lo agregamos al préstamo // Buscamos el passcode y se lo agregamos al préstamo
return this.passcodeService return this.passcodeService.findByPrestamo(prestamo).then((passcode) => {
.findByPrestamo(prestamo) Object.assign(prestamo, passcode);
.then((passcode) => ({ ...prestamo, passcode: passcode.passcode })); return prestamo;
});
return prestamo; return prestamo;
} }
@@ -724,6 +795,9 @@ export class PrestamoService {
): Promise<{ message: string }> { ): Promise<{ message: string }> {
const ahora = moment(); const ahora = moment();
const status = await this.statusService.findById(id_status); const status = await this.statusService.findById(id_status);
if (this.add) ahora.add(this.add, 'h');
const tardanza = Math.trunc(ahora.diff(moment(prestamo.hora_fin)) / 60000); // Si la resta ahora - hora_fin es positiva es que ya se tardo en entregar const tardanza = Math.trunc(ahora.diff(moment(prestamo.hora_fin)) / 60000); // Si la resta ahora - hora_fin es positiva es que ya se tardo en entregar
const semanasCastigo = Math.trunc( const semanasCastigo = Math.trunc(
tardanza / modulo.institucion.tiempo_entrega, tardanza / modulo.institucion.tiempo_entrega,
@@ -798,7 +872,9 @@ export class PrestamoService {
.then((_) => this.repository.save(prestamo)) // Guardamos cambios en el préstamo .then((_) => this.repository.save(prestamo)) // Guardamos cambios en el préstamo
.then((_) => { .then((_) => {
// Actualizamos la interfaz del usuario // Actualizamos la interfaz del usuario
this.appGateway.actualizarUsuario(prestamo.usuario.id_usuario); this.appGateway.actualizarUsuario(
prestamo.institucionUsuario.usuario.id_usuario,
);
return { message: 'Se regresó el equipo de cómputo correctamente.' }; return { message: 'Se regresó el equipo de cómputo correctamente.' };
}); });
} }
@@ -854,35 +930,6 @@ export class PrestamoService {
return this.repository.save(prestamo); return this.repository.save(prestamo);
} }
private validarInstitucionUsuario(
instituciones: InstitucionUsuario[],
modulo: Modulo,
): InstitucionUsuario {
// Recorremos array de instituciones usuario
for (let i = 0; i < instituciones.length; i++) {
const institucion = instituciones[i].institucionCarrera.institucion;
// Si encontramos una institución usuario cuyo id institución sea igual al del módulo enviado
if (institucion.id_institucion === modulo.institucion.id_institucion) {
// Validamos que este activo
if (!instituciones[i].activo)
throw new ForbiddenException(
`${this.mensajeNoPoderPedir()} tu cuenta esta desactivada en esta institución.`,
);
// Validamos que no tenga multa
if (instituciones[i].multa)
throw new ForbiddenException(
`${this.mensajeNoPoderPedir()} tienes una multa activa.`,
);
return instituciones[i];
}
}
// Si no se encuentra una institución usuario que sea igual que la del módulo enviado sacamos error
throw new BadRequestException(
`${this.mensajeNoPoderPedir()} no perteneces a la institución del módulo seleccionado.`,
);
}
private validacionBasicaPrestamo(prestamo: Prestamo): void { private validacionBasicaPrestamo(prestamo: Prestamo): void {
// Validamos si el préstamo ya fue cancelado por el usuario // Validamos si el préstamo ya fue cancelado por el usuario
if (prestamo.cancelado_usuario) if (prestamo.cancelado_usuario)
@@ -949,7 +996,13 @@ export class PrestamoService {
}, },
operadorEntrega: { id_operador: infoPrestamo.id_operador_entrega }, operadorEntrega: { id_operador: infoPrestamo.id_operador_entrega },
operadorRegreso: { id_operador: infoPrestamo.id_operador_regreso }, operadorRegreso: { id_operador: infoPrestamo.id_operador_regreso },
usuario: { id_usuario: infoPrestamo.id_usuario }, institucionUsuario: {
id_institucion_usuario: infoPrestamo.id_institucion_usuario,
institucionCarrera: {
id_institucion_carrera: infoPrestamo.id_institucion_carrera,
},
usuario: { id_usuario: infoPrestamo.id_usuario },
},
}); });
} }
} }
-4
View File
@@ -7,7 +7,6 @@ import {
PrimaryGeneratedColumn, PrimaryGeneratedColumn,
} from 'typeorm'; } from 'typeorm';
import { InstitucionUsuario } from '../../institucion-usuario/entity/institucion-usuario.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'; import { TipoUsuario } from '../../tipo-usuario/entity/tipo-usuario.entity';
@Entity() @Entity()
@@ -47,7 +46,4 @@ export class Usuario {
(institucionUsuario) => institucionUsuario.usuario, (institucionUsuario) => institucionUsuario.usuario,
) )
instituciones: InstitucionUsuario[]; instituciones: InstitucionUsuario[];
@OneToMany(() => Prestamo, (prestamo) => prestamo.usuario)
prestamos: Prestamo[];
} }
+2 -2
View File
@@ -17,7 +17,7 @@ import {
ApiTags, ApiTags,
} from '@nestjs/swagger'; } from '@nestjs/swagger';
import { Serealize } from '../interceptors/serialize.interceptor'; import { Serealize } from '../interceptors/serialize.interceptor';
import { HcaptchaGuard } from '../guards/hcaptcha.guard'; import { TurnstileGuard } from '../guards/turnstile.guard';
import { UsuarioService } from './usuario.service'; import { UsuarioService } from './usuario.service';
import { ValidarUsuarioService } from '../validar-usuario/validar-usuario.service'; import { ValidarUsuarioService } from '../validar-usuario/validar-usuario.service';
import { Operador } from '../operador/entity/operador.entity'; import { Operador } from '../operador/entity/operador.entity';
@@ -39,7 +39,7 @@ export class UsuarioController {
@Serealize(MessageOutputDto) @Serealize(MessageOutputDto)
@Post('registrar') @Post('registrar')
@UseGuards(HcaptchaGuard) @UseGuards(TurnstileGuard)
@ApiOperation({ description: 'Registro de usuario.' }) @ApiOperation({ description: 'Registro de usuario.' })
@ApiBody({ @ApiBody({
description: 'Variables que necesita el endpoint.', description: 'Variables que necesita el endpoint.',