Files
pcpuma_unam_api/src/prestamo/prestamo.service.ts
T
xXpuma99Xx fd0f87476a cron listo
2022-06-16 08:02:37 -05:00

506 lines
17 KiB
TypeScript

import * as moment from 'moment';
import {
ConflictException,
forwardRef,
Inject,
Injectable,
NotFoundException,
} from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { FindOperator, Like, Repository } from 'typeorm';
import { Institucion } from '../institucion/entity/institucion.entity';
import { Modulo } from '../modulo/entity/modulo.entity';
import { Operador } from '../operador/entity/operador.entity';
import { Prestamo } from './entity/prestamo.entity';
import { TipoCarrito } from '../institucion-tipo-carrito/entity/tipo-carrito.entity';
import { TipoUsuario } from '../tipo-usuario/entity/tipo-usuario.entity';
import { EquipoService } from '../equipo/equipo.service';
import { InstitucionService } from '../institucion/institucion.service';
import { InstitucionDiaService } from '../institucion-dia/institucion-dia.service';
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 { ModuloService } from '../modulo/modulo.service';
import { MotivoService } from '../motivo/motivo.service';
import { MultaService } from '../multa/multa.service';
import { OperadorService } from '../operador/operador.service';
import { StatusService } from '../status/status.service';
import { TipoUsuarioService } from '../tipo-usuario/tipo-usuario.service';
import { UsuarioService } from '../usuario/usuario.service';
@Injectable()
export class PrestamoService {
constructor(
@InjectRepository(Prestamo) private repository: Repository<Prestamo>,
private equipoService: EquipoService,
private institucionService: InstitucionService,
private institucionDiaService: InstitucionDiaService,
private institucionProgramaService: InstitucionProgramaService,
private institucionTipoCarritoService: InstitucionTipoCarritoService,
private institucionTipoEntradaService: InstitucionTipoEntradaService,
private moduloService: ModuloService,
private motivoService: MotivoService,
@Inject(forwardRef(() => MultaService))
private multaService: MultaService,
private operadorService: OperadorService,
private statusService: StatusService,
private tipoUsuarioService: TipoUsuarioService,
private usuarioService: UsuarioService,
) {}
async cancelarOperador(
id_prestamo: number,
id_operador: number,
motivo: string,
) {
const ahora = moment();
const revisar = await this.statusService.findById(6);
const operadorRegreso = await this.operadorService.findById(id_operador);
const prestamo = await this.findById(id_prestamo);
this.validacionBasicaPrestamo(prestamo);
prestamo.activo = false;
prestamo.fecha_entrega = ahora.toDate();
prestamo.cancelado_operador = true;
prestamo.operadorRegreso = operadorRegreso;
prestamo.equipo.status = revisar;
return this.equipoService
.update(prestamo.equipo)
.then((_) =>
this.motivoService.create(
prestamo.equipo,
operadorRegreso,
revisar,
motivo,
),
)
.then((_) => this.repository.save(prestamo))
.then((_) => ({ message: 'Se canceló correctamente este préstamo.' }));
}
async cancelarUsuario(id_prestamo: number) {
const ahora = moment();
const prestamo = await this.findById(id_prestamo);
this.validacionBasicaPrestamo(prestamo);
if (prestamo.equipo.status.id_status === 3)
throw new ConflictException(
'No se puede cancelar el préstamo una vez se te entregó el equipo.',
);
prestamo.activo = false;
prestamo.fecha_entrega = ahora.toDate();
prestamo.cancelado_usuario = true;
prestamo.equipo.status = await this.statusService.findById(1);
return this.equipoService
.update(prestamo.equipo)
.then((_) => this.repository.save(prestamo))
.then((_) => ({ message: 'Se canceló correctamente este préstamo.' }));
}
async create(
id_usuario: number,
id_modulo: number,
id_tipo_carrito: number,
id_programa?: number,
id_tipo_entrada?: number,
) {
const ahora = moment();
const usuario = await this.usuarioService.findById(id_usuario, true, true);
const modulo = await this.moduloService.findById(id_modulo);
const tipoCarrito =
await this.institucionTipoCarritoService.findTipoCarritoById(
id_tipo_carrito,
);
const programa = id_programa
? await this.institucionProgramaService.findProgramaById(id_programa)
: null;
const tipoEntrada = id_tipo_entrada
? await this.institucionTipoEntradaService.findTipoEntradaById(
id_tipo_entrada,
)
: null;
// if (ahora.weekday() === 0 || ahora.weekday() === 6)
// throw new ConflictException(
// 'No se puede pedir equipo de cómputo los sabados y domingos.',
// );
// else {
// const institucionDia = await this.institucionDiaService.findDia(
// modulo.institucion,
// ahora.weekday(),
// );
// const horaMax = moment(
// `${ahora.format('YYYY-MM-DD')} ${institucionDia.hora_fin}`,
// );
// const horaMin = moment(
// `${ahora.format('YYYY-MM-DD')} ${institucionDia.hora_inicio}`,
// );
// if (!institucionDia.activo)
// throw new ConflictException(
// 'El día de hoy no se esta realizando préstamos de equipos.',
// );
// if (ahora > horaMax)
// throw new Error('Ya no se puede realizar un préstamo el día de hoy.');
// 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.',
);
return this.repository
.findOne({ activo: true, usuario })
.then((existePrestamo) => {
if (existePrestamo)
throw new ConflictException(
'Este usuario ya tiene un préstamo activo.',
);
return this.equipoService.reseteo(
modulo,
tipoCarrito,
programa,
tipoEntrada,
);
})
.then((_) =>
this.equipoService
.findEquipo(modulo, tipoCarrito, programa, tipoEntrada)
.getOne(),
)
.then(async (equipo) => {
if (!equipo)
throw new ConflictException(
'No hay un equipo de cómputo que cumpla con las caracteríasticas solicitasdas o ya no hay equipos disponibles en este momento. Intenta más tarde o cambia las caracteríasticas.',
);
equipo.status = await this.statusService.findById(2);
return this.equipoService.update(equipo);
})
.then(({ equipo }) =>
this.repository.save(
this.repository.create({
equipo,
usuario,
fecha_inicio: ahora.toDate(),
hora_max_recoger: ahora
.add(modulo.institucion.tiempo_recoger, 'm')
.toDate(),
}),
),
);
}
async desactivarPrestamos() {
const ahora = moment();
const operadorRegreso = await this.operadorService.findById(1);
return this.repository
.find({
join: { alias: 'p', innerJoin: { e: 'p.equipo' } },
where: { activo: true, equipo: { status: { id_status: 2 } } },
})
.then(async (prestamos) => {
for (let i = 0; i < prestamos.length; i++)
if (ahora.diff(moment(prestamos[i].hora_max_recoger)) > 0) {
prestamos[i].activo = false;
prestamos[i].cancelado_operador = true;
prestamos[i].operadorRegreso = operadorRegreso;
prestamos[i].equipo.status = await this.statusService.findById(1);
await this.equipoService
.update(prestamos[i].equipo)
.then((_) => this.repository.save(prestamos[i]));
}
});
}
async entregar(id_prestamo: number, id_operador: number) {
const ahora = moment();
const operadorEntrega = await this.operadorService.findById(id_operador);
const prestamo = await this.findById(id_prestamo);
this.validacionBasicaPrestamo(prestamo);
if (prestamo.equipo.status.id_status === 3)
throw new ConflictException(
'Ya se entregó el equipo de cómputo al usuario.',
);
prestamo.hora_inicio = ahora.toDate();
prestamo.hora_fin = ahora
.add(operadorEntrega.institucion.tiempo_prestamo, 'm')
.toDate();
prestamo.operadorEntrega = operadorEntrega;
prestamo.equipo.status = await this.statusService.findById(3);
prestamo.equipo.prestado = true;
return this.equipoService
.update(prestamo.equipo)
.then((_) => this.repository.save(prestamo))
.then((_) => ({
message: 'Se entregó el equipo de cómputo correctamente.',
}));
}
async findAll(filtros: {
pagina: string;
activo?: string | boolean;
carrito?: string;
equipo?: string;
fechaFin?: string;
fechaInicio?: string;
id_institucion?: string;
id_modulo?: string;
id_operador_entrega?: string;
id_operador_regreso?: string;
id_prestamo?: string;
id_tipo_carrito?: string;
id_tipo_usuario?: string;
usuario?: string;
}) {
const busqueda: {
activo?: boolean;
fechaInicio?: Date;
fechaFin?: Date;
id_prestamo?: FindOperator<string>;
equipo: {
equipo?: FindOperator<string>;
carrito: {
carrito?: FindOperator<string>;
modulo?: Modulo | { institucion: Institucion };
tipoCarrito?: TipoCarrito;
};
};
usuario: {
usuario?: FindOperator<string>;
tipoUsuario?: TipoUsuario;
};
operadorEntrega?: Operador;
operadorRegreso?: Operador;
} = {
equipo: { carrito: {} },
usuario: {},
};
const institucion = filtros.id_institucion
? await this.institucionService.findById(parseInt(filtros.id_institucion))
: null;
const modulo = filtros.id_modulo
? await this.moduloService.findById(parseInt(filtros.id_modulo))
: null;
const tipoCarrito = filtros.id_tipo_carrito
? await this.institucionTipoCarritoService.findTipoCarritoById(
parseInt(filtros.id_tipo_carrito),
)
: null;
const tipoUsuario = filtros.id_tipo_usuario
? await this.tipoUsuarioService.findById(
parseInt(filtros.id_tipo_usuario),
)
: null;
const operadorEntrega = filtros.id_operador_entrega
? await this.operadorService.findById(
parseInt(filtros.id_operador_entrega),
)
: null;
const operadorRegreso = filtros.id_operador_regreso
? await this.operadorService.findById(
parseInt(filtros.id_operador_regreso),
)
: null;
if (filtros.activo) {
if (typeof filtros.activo === 'boolean') busqueda.activo = filtros.activo;
else busqueda.activo = filtros.activo === 'true';
}
if (filtros.carrito)
busqueda.equipo.carrito.carrito = Like(`%${filtros.carrito}%`);
if (filtros.equipo) busqueda.equipo.equipo = Like(`%${filtros.equipo}%`);
if (filtros.id_prestamo) busqueda.id_prestamo = Like(filtros.id_prestamo);
if (filtros.usuario)
busqueda.usuario.usuario = Like(`%${filtros.usuario}%`);
if (institucion) busqueda.equipo.carrito.modulo = { institucion };
if (modulo) busqueda.equipo.carrito.modulo = modulo;
if (operadorEntrega) busqueda.operadorEntrega = operadorEntrega;
if (operadorRegreso) busqueda.operadorRegreso = operadorRegreso;
if (tipoCarrito) busqueda.equipo.carrito.tipoCarrito = tipoCarrito;
if (tipoUsuario) busqueda.usuario.tipoUsuario = tipoUsuario;
return this.repository.findAndCount({
join: {
alias: 'p',
innerJoinAndSelect: {
e: 'p.equipo',
u: 'p.usuario',
c: 'e.carrito',
m: 'c.modulo',
tc: 'c.tipoCarrito',
},
},
where: busqueda,
skip: (parseInt(filtros.pagina) - 1) * 25,
take: 25,
});
}
findAllByIdUsuario(id_usuario: number, pagina: number) {
return this.usuarioService
.findById(id_usuario, true, true)
.then((usuario) =>
this.repository.findAndCount({
where: { usuario },
skip: (pagina - 1) * 25,
take: 25,
}),
);
}
async findAllByIdEquipo(id_equipo: number, pagina: number) {
return this.equipoService.findById(id_equipo).then((equipo) =>
this.repository.findAndCount({
where: { equipo },
skip: (pagina - 1) * 25,
take: 25,
}),
);
}
findById(id_prestamo: number) {
return this.repository.findOne({ id_prestamo }).then((prestamo) => {
if (!prestamo) throw new NotFoundException('No existe este préstamo.');
return prestamo;
});
}
findByIdUsuario(id_usuario: number) {
return this.usuarioService
.findById(id_usuario, true, true)
.then((usuario) => this.repository.findOne({ usuario, activo: true }))
.then((prestamo) => {
if (!prestamo)
throw new NotFoundException(
'Este usuario no tiene un prestamo activo.',
);
return prestamo;
});
}
async findByNumeroInventario(
id_institucion: number | Institucion,
numero_inventario: string,
) {
const institucion =
typeof id_institucion === 'number'
? await this.institucionService.findById(id_institucion)
: id_institucion;
return this.equipoService
.findByNumeroInventario(institucion, numero_inventario)
.then((equipo) => this.repository.findOne({ equipo, activo: true }))
.then((prestamo) => {
if (!prestamo)
throw new NotFoundException(
'No existe este un préstamo activo con este equipo de cómputo.',
);
return prestamo;
});
}
async regresar(
prestamo: Prestamo,
operadorRegreso: Operador,
descripcion?: string,
id_institucion_infraccion?: number,
) {
const ahora = moment();
const tardanza = Math.trunc(ahora.diff(moment(prestamo.hora_fin)) / 60000);
const semanasCastigo = Math.trunc(
tardanza / operadorRegreso.institucion.tiempo_entrega,
);
this.validacionBasicaPrestamo(prestamo);
if (prestamo.equipo.status.id_status === 2)
throw new ConflictException('Aun no se entrega el equipo al usuario.');
if (id_institucion_infraccion && !descripcion)
throw new ConflictException('No se mandó la descripción de lo ocurrido.');
prestamo.activo = false;
prestamo.fecha_entrega = ahora.toDate();
prestamo.operadorRegreso = operadorRegreso;
prestamo.equipo.status = await this.statusService.findById(1);
if (semanasCastigo > 0) {
if (id_institucion_infraccion)
await this.multaService.create(
prestamo,
operadorRegreso,
`El usaurio se tardó: ${tardanza} minutos en entregar el equipo de cómputo. ${descripcion}`,
semanasCastigo,
id_institucion_infraccion,
);
else
await this.multaService.create(
prestamo,
operadorRegreso,
`El usaurio se tardó: ${tardanza} minutos en entregar el equipo de cómputo.`,
semanasCastigo,
);
} else if (id_institucion_infraccion)
await this.multaService.create(
prestamo,
operadorRegreso,
descripcion,
null,
id_institucion_infraccion,
);
return this.equipoService
.update(prestamo.equipo)
.then((_) => this.repository.save(prestamo))
.then((_) => ({
message: 'Se regresó el equipo de cómputo correctamente.',
}));
}
async regresarIdPrestamo(
id_operador: number,
id_prestamo: number,
descripcion?: string,
id_institucion_infraccion?: number,
) {
const operador = await this.operadorService.findById(id_operador);
const prestamo = await this.findById(id_prestamo);
return this.regresar(
prestamo,
operador,
descripcion,
id_institucion_infraccion,
);
}
async regresarNumeroInventario(
id_operador: number,
numero_inventario: string,
descripcion?: string,
id_institucion_infraccion?: number,
) {
const operador = await this.operadorService.findById(id_operador);
const prestamo = await this.findByNumeroInventario(
operador.institucion,
numero_inventario,
);
return this.regresar(
prestamo,
operador,
descripcion,
id_institucion_infraccion,
);
}
validacionBasicaPrestamo(prestamo: Prestamo) {
if (prestamo.cancelado_usuario)
throw new ConflictException(
'Este préstamo fue cancelado por el usuario.',
);
if (prestamo.cancelado_operador)
throw new ConflictException(
'Este préstamo fue cancelado por un operador.',
);
if (!prestamo.activo)
throw new ConflictException('Este préstamo ya no se encuentra activo.');
}
}