import { ConflictException, ForbiddenException, forwardRef, Inject, Injectable, NotFoundException, } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { FindOptionsWhere, Repository } from 'typeorm'; import { Carrito } from '../carrito/entity/carrito.entity'; import { Equipo } from './entity/equipo.entity'; import { Institucion } from '../institucion/entity/institucion.entity'; import { Marca } from '../marca/entity/marca.entity'; import { Modelo } from '../modelo/entity/modelo.entity'; import { Modulo } from '../modulo/entity/modulo.entity'; import { Operador } from '../operador/entity/operador.entity'; import { Programa } from '../institucion-programa/entity/programa.entity'; import { TipoCarrito } from '../institucion-tipo-carrito/entity/tipo-carrito.entity'; import { TipoEntrada } from '../institucion-tipo-entrada/entity/tipo-entrada.entity'; import { FullInformacionEquipoView } from './entity/views/full-informacion-equipo.view'; import { InformacionEquipoPrestamoView } from './entity/views/informacion-equipo-prestamo.view'; import { InformacionEquipoView } from './entity/views/informacion-equipo.view'; import { CarritoService } from '../carrito/carrito.service'; import { EquipoProgramaService } from '../equipo-programa/equipo-programa.service'; import { EquipoTipoEntradaService } from '../equipo-tipo-entrada/equipo-tipo-entrada.service'; import { InstitucionService } from '../institucion/institucion.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 { MarcaService } from '../marca/marca.service'; import { ModeloService } from '../modelo/modelo.service'; import { ModuloService } from '../modulo/modulo.service'; import { EquipoMotivoService } from '../equipo-motivo/equipo-motivo.service'; import { StatusService } from '../status/status.service'; @Injectable() export class EquipoService { constructor( @InjectRepository(Equipo) private repository: Repository, @InjectRepository(FullInformacionEquipoView) private fullInformacionEquipoView: Repository, @InjectRepository(InformacionEquipoPrestamoView) private informacionEquipoPrestamoView: Repository, @InjectRepository(InformacionEquipoView) private informacionEquipoView: Repository, private carritoService: CarritoService, @Inject(forwardRef(() => EquipoProgramaService)) private equipoProgramaService: EquipoProgramaService, @Inject(forwardRef(() => EquipoTipoEntradaService)) private equipoTipoEntradaService: EquipoTipoEntradaService, private institucionService: InstitucionService, private institucionProgramaService: InstitucionProgramaService, private institucionTipoCarritoService: InstitucionTipoCarritoService, private institucionTipoEntradaService: InstitucionTipoEntradaService, private marcaService: MarcaService, private modeloService: ModeloService, private moduloService: ModuloService, @Inject(forwardRef(() => EquipoMotivoService)) private equipoMotivoService: EquipoMotivoService, private statusService: StatusService, ) {} async create( carrito: Carrito, equipo: string, numero_inventario: string, numero_serie: string, marca: Marca, modelo: Modelo, ) { const equipoNuevo = await this.repository.save( this.repository.create({ carrito, equipo, marca, modelo, numero_inventario, numero_serie, status: { id_status: 1 }, }), ); return this.equipoProgramaService .createSinPrograma(equipoNuevo) .then((_) => equipoNuevo); } async findAll( operador: Operador, filtros: { pagina: string; carrito?: string; equipo?: string; id_carrito?: string; id_institucion?: string; id_marca?: string; id_modelo?: string; id_modulo?: string; id_programa?: string; id_status?: string; id_tipo_carrito?: string; id_tipo_entrada?: string; }, ) { const carrito = filtros.id_carrito ? await this.carritoService.findById(parseInt(filtros.id_carrito)) : null; const institucion = filtros.id_institucion ? await this.institucionService.findInfoInstitucionById( parseInt(filtros.id_institucion), ) : null; const marca = filtros.id_marca ? await this.marcaService.findById(parseInt(filtros.id_marca), 'e') : null; const modelo = filtros.id_modelo ? await this.modeloService.findById(parseInt(filtros.id_modelo), 'e') : null; const modulo = filtros.id_modulo ? await this.moduloService.findInfoModuloById(parseInt(filtros.id_modulo)) : null; const programa = filtros.id_programa ? await this.institucionProgramaService.findProgramaById( parseInt(filtros.id_programa), ) : null; const tipoCarrito = filtros.id_tipo_carrito ? await this.institucionTipoCarritoService.findTipoCarritoById( parseInt(filtros.id_tipo_carrito), ) : null; const status = filtros.id_status ? await this.statusService.findById(parseInt(filtros.id_status)) : null; const tipoEntrada = filtros.id_tipo_entrada ? await this.institucionTipoEntradaService.findTipoEntradaById( parseInt(filtros.id_tipo_entrada), ) : null; const query = this.repository .createQueryBuilder('e') .innerJoinAndSelect('e.carrito', 'c') .innerJoinAndSelect('e.marca', 'ma') .innerJoinAndSelect('e.modelo', 'mo') .innerJoinAndSelect('e.programas', 'ps') .innerJoinAndSelect('e.status', 's') .innerJoinAndSelect('e.tiposEntradas', 'tes') .innerJoinAndSelect('c.modulo', 'm') .innerJoinAndSelect('c.tipoCarrito', 'tc') .innerJoinAndSelect('ps.programa', 'p') .innerJoinAndSelect('tes.tipoEntrada', 'te') .innerJoinAndSelect('m.institucion', 'i') .orderBy('i.institucion') .addOrderBy('m.modulo') .addOrderBy('tc.tipo_carrito') .addOrderBy('c.carrito') .addOrderBy('e.equipo') .take(15) .skip((parseInt(filtros.pagina) - 1) * 15); if (modulo) { if ( operador.tipoUsuario.id_tipo_usuario > 2 && operador.institucion.id_institucion != modulo.institucion.id_institucion ) throw new ForbiddenException( 'No puedes acceder a esta información porque este módulo no pertenece a tu institución.', ); query.andWhere('m.id_modulo = :id_modulo', { id_modulo: modulo.id_modulo, }); } if (carrito) { if ( operador.tipoUsuario.id_tipo_usuario > 2 && operador.institucion.id_institucion != carrito.modulo.institucion.id_institucion ) throw new ForbiddenException( 'No puedes acceder a esta información porque este carrito no pertenece a tu institución.', ); query.andWhere('c.id_carrito = :id_carrito', { id_carrito: carrito.id_carrito, }); } if (filtros.carrito) query.andWhere('c.carrito LIKE :carrito', { carrito: `%${filtros.carrito}%`, }); if (filtros.equipo) query.andWhere('e.equipo LIKE :equipo', { equipo: `%${filtros.equipo}%`, }); if (institucion) query.andWhere('m.id_institucion = :id_institucion', { id_institucion: institucion.id_institucion, }); if (marca) query.andWhere('ma.id_marca = :id_marca', { id_marca: marca.id_marca, }); if (modelo) query.andWhere('mo.id_modelo = :id_modelo', { id_modelo: modelo.id_modelo, }); if (programa) query.andWhere('ps.id_programa = :id_programa', { id_programa: programa.id_programa, }); if (tipoCarrito) query.andWhere('tc.id_tipo_carrito = :id_tipo_carrito', { id_tipo_carrito: tipoCarrito.id_tipo_carrito, }); if (tipoEntrada) query.andWhere('tes.id_tipo_entrada = :id_tipo_entrada', { id_tipo_entrada: tipoEntrada.id_tipo_entrada, }); if (status) query.andWhere('s.id_status = :id_status', { id_status: status.id_status, }); return query.getManyAndCount(); } async findEquipo( id_usuario: number, modulo: Modulo, tipoCarrito: TipoCarrito, programa?: Programa, tipoEntrada?: TipoEntrada, ) { const busquedaReseteo: FindOptionsWhere = { prestado: 1, id_modulo: modulo.id_modulo, id_tipo_carrito: tipoCarrito.id_tipo_carrito, }; const busqueda: FindOptionsWhere = { prestado: 0, id_modulo: modulo.id_modulo, id_tipo_carrito: tipoCarrito.id_tipo_carrito, }; if (programa) { busqueda.id_programa = programa.id_programa; busquedaReseteo.id_programa = programa.id_programa; } else { busqueda.id_programa = 1; busquedaReseteo.id_programa = 1; } if (tipoEntrada) { busqueda.id_tipo_entrada = tipoEntrada.id_tipo_entrada; busquedaReseteo.id_tipo_entrada = tipoEntrada.id_tipo_entrada; } return this.informacionEquipoPrestamoView .findOne({ where: busqueda }) .then((infoEquipo) => { if (!infoEquipo) return this.informacionEquipoPrestamoView .find({ where: busquedaReseteo }) .then(async (infoEquipos) => { for (let i = 0; i < infoEquipos.length; i++) await this.repository.save( this.repository.create({ id_equipo: infoEquipos[i].id_equipo, prestado: false, }), ); return this.informacionEquipoPrestamoView.findOne({ where: busqueda, }); }) .then((infoEquipo) => { if (!infoEquipo) throw new ConflictException( 'No hay un equipo de cómputo que cumpla con las caracteríasticas solicitadas o ya no hay equipos disponibles en este momento. Intenta más tarde o cambia las características.', ); return infoEquipo; }); return infoEquipo; }) .then((infoEquipo) => { if (infoEquipo.u) throw new ConflictException( 'Ocurrio un error al tratar de asignarte un equipo de cómputo, intenta de nuevo.', ); const equipo = this.repository.create({ id_equipo: infoEquipo.id_equipo, u: id_usuario, status: { id_status: 2 }, }); return this.repository.save(equipo); }) .then((equipo) => this.findInfoEquipoById(equipo.id_equipo)) .then((equipo) => { if (equipo.u != id_usuario) throw new ConflictException( 'Ocurrio un error al tratar de asignarte un equipo de cómputo, intenta de nuevo.', ); return equipo; }); } findInfoEquipoById(id_equipo: number) { return this.informacionEquipoView .findOne({ where: { id_equipo } }) .then((infoEquipo) => { if (!infoEquipo) throw new NotFoundException('No existe este id equipo.'); return this.viewToEquipo(infoEquipo); }); } findInfoEquipoByNumeroInventario( institucion: Institucion, numero_inventario: string, validarNoExiste = true, ) { return this.informacionEquipoView .findOne({ where: { id_institucion: institucion.id_institucion, numero_inventario, }, }) .then((infoEquipo) => { if (!infoEquipo) { if (validarNoExiste) throw new NotFoundException( 'No existe un equipo de cómputo con este número de inventario.', ); return null; } return this.viewToEquipo(infoEquipo); }); } async findInfoEquipoByEquipo( carrito: Carrito, equipo: string, validarNoExiste = true, ) { return this.informacionEquipoView .findOne({ where: { id_carrito: carrito.id_carrito, equipo, }, }) .then((infoEquipo) => { if (!infoEquipo) { if (validarNoExiste) throw new NotFoundException( 'No existe un equipo de cómputo con este número de inventario.', ); return null; } return this.viewToEquipo(infoEquipo); }); } findFullInfoEquipoByNumeroInventario( id_institucion: number, numero_inventario: string, ) { return this.institucionService .findInfoInstitucionById(id_institucion) .then((institucion) => this.fullInformacionEquipoView.findOne({ where: { id_institucion: institucion.id_institucion, numero_inventario, }, }), ) .then(async (infoEquipo) => { if (!infoEquipo) throw new NotFoundException( 'No existe un equipo de cómputo con este número de inventario.', ); const programas = await this.equipoProgramaService.findFullInfoEquipoProgramaAllByIdEquipo( infoEquipo.id_equipo, ); const tiposEntradas = await this.equipoTipoEntradaService.findFullInfoEquipoTipoEntradaAllByIdEquipo( infoEquipo.id_equipo, ); return this.repository.create({ id_equipo: infoEquipo.id_equipo, equipo: infoEquipo.equipo, numero_inventario: infoEquipo.numero_inventario, prestado: infoEquipo.prestado, carrito: { id_carrito: infoEquipo.id_carrito, carrito: infoEquipo.carrito, modulo: { id_modulo: infoEquipo.id_modulo, modulo: infoEquipo.modulo, institucion: { id_institucion: infoEquipo.id_institucion, institucion: infoEquipo.institucion, }, }, tipoCarrito: { id_tipo_carrito: infoEquipo.id_tipo_carrito, tipo_carrito: infoEquipo.tipo_carrito, }, }, marca: { id_marca: infoEquipo.id_marca, marca: infoEquipo.marca, }, modelo: { id_modelo: infoEquipo.id_modelo, modelo: infoEquipo.modelo, }, status: { id_status: infoEquipo.id_status, status: infoEquipo.status, }, programas, tiposEntradas, }); }); } reseteoTotal() { return this.repository .createQueryBuilder() .update() .set({ prestado: false }) .execute(); } async update( operador: Operador, attrs: Partial, id_carrito?: number, id_status?: number, motivo?: string, ) { const carrito = id_carrito ? await this.carritoService.findById(id_carrito) : null; const status = id_status ? await this.statusService.findById(id_status) : null; return this.findInfoEquipoById(attrs.id_equipo) .then(async (equipo) => { if ( operador.tipoUsuario.id_tipo_usuario > 2 && operador.institucion.id_institucion != equipo.carrito.modulo.institucion.id_institucion ) throw new ForbiddenException( 'No puedes modificar la información este equipo porque no pertenece a tu institución.', ); if (status) { if (equipo.status.id_status === 2 || equipo.status.id_status === 3) throw new ConflictException( 'No se puede cambiar el status de un equipo si esta apartada o en uso.', ); if (status.id_status === 2 || status.id_status === 3) throw new ConflictException( 'No se puede cambiar manualmente el status de un equipo a este status.', ); if (!motivo) throw new ConflictException( 'No se mandó el motivo para el cambio de status.', ); } Object.assign(equipo, attrs); if (status) { equipo.status = status; await this.equipoMotivoService.create( equipo, operador, status, motivo, ); } if (carrito) equipo.carrito = carrito; return this.repository.save(equipo); }) .then((_) => ({ message: 'Se guardaron los cambios correctamente.', })); } async updateStatus(equipo: Equipo, operador?: Operador, motivo?: string) { if (equipo.status.id_status >= 4) { if (!operador) throw new ConflictException('No se mandó el id operador.'); if (!motivo) throw new ConflictException( 'No se mandó el motivo para el cambio de status.', ); await this.equipoMotivoService.create( equipo, operador, equipo.status, motivo, ); } return this.repository.save(equipo); } private viewToEquipo(infoEquipo: InformacionEquipoView) { return this.repository.create({ id_equipo: infoEquipo.id_equipo, equipo: infoEquipo.equipo, numero_inventario: infoEquipo.numero_inventario, prestado: infoEquipo.prestado, u: infoEquipo.u, carrito: { id_carrito: infoEquipo.id_carrito, carrito: infoEquipo.carrito, modulo: { id_modulo: infoEquipo.id_modulo, institucion: { id_institucion: infoEquipo.id_institucion }, }, tipoCarrito: { id_tipo_carrito: infoEquipo.id_tipo_carrito }, }, status: { id_status: infoEquipo.id_status }, }); } }