1790 lines
52 KiB
TypeScript
1790 lines
52 KiB
TypeScript
import {
|
|
BadRequestException,
|
|
Injectable,
|
|
NotFoundException,
|
|
} from '@nestjs/common';
|
|
import { InjectRepository } from '@nestjs/typeorm';
|
|
import { Repository } from 'typeorm';
|
|
import { Equipo } from './entities/equipo.entity';
|
|
import { UpdateEquipoDto } from './dto/update-equipo.dto';
|
|
import axios from 'axios';
|
|
import e, { Response } from 'express';
|
|
import * as ExcelJS from 'exceljs';
|
|
|
|
import {
|
|
Adscripcion,
|
|
Estado,
|
|
Laboratorio,
|
|
Marca,
|
|
Periferico,
|
|
Procesador,
|
|
Proyecto,
|
|
SistemaOperativo,
|
|
TipoEquipo,
|
|
Uso,
|
|
} from './entities/catalogo.entities';
|
|
|
|
import { CreateEquipoDto } from './dto/create-equipo.dto';
|
|
|
|
import { MovimientoService } from 'src/movimiento/movimiento.service';
|
|
import { Cron } from '@nestjs/schedule';
|
|
import { FiltrosGraficaDto, FiltrosTablaDto } from './dto/grafica.dto';
|
|
|
|
@Injectable()
|
|
export class EquipoService {
|
|
constructor(
|
|
private readonly movimiento: MovimientoService,
|
|
|
|
@InjectRepository(Equipo)
|
|
private readonly equipoRepository: Repository<Equipo>,
|
|
@InjectRepository(Uso)
|
|
private readonly usoRepo: Repository<Uso>,
|
|
|
|
@InjectRepository(Marca)
|
|
private readonly marcaRepo: Repository<Marca>,
|
|
|
|
@InjectRepository(Estado)
|
|
private readonly estadoRepo: Repository<Estado>,
|
|
|
|
@InjectRepository(Adscripcion)
|
|
private readonly adscripcionRepo: Repository<Adscripcion>,
|
|
|
|
@InjectRepository(TipoEquipo)
|
|
private readonly tipoEquipoRepo: Repository<TipoEquipo>,
|
|
|
|
@InjectRepository(SistemaOperativo)
|
|
private readonly sistemaOperativoRepo: Repository<SistemaOperativo>,
|
|
|
|
@InjectRepository(Procesador)
|
|
private readonly procesadorRepo: Repository<Procesador>,
|
|
|
|
@InjectRepository(Periferico)
|
|
private readonly perifericoRepo: Repository<Periferico>,
|
|
@InjectRepository(Laboratorio)
|
|
private readonly laboratorioRepo: Repository<Laboratorio>,
|
|
@InjectRepository(Proyecto)
|
|
private readonly proyectoRepo: Repository<Proyecto>,
|
|
) { }
|
|
|
|
async deleteEquipo(inventario: string): Promise<{ message: string }> {
|
|
const equipo = await this.equipoRepository.findOne({
|
|
where: { inventario },
|
|
});
|
|
|
|
if (!equipo) {
|
|
throw new NotFoundException(
|
|
`No se encontró el equipo con id ${inventario}`,
|
|
);
|
|
}
|
|
|
|
await this.equipoRepository.remove(equipo);
|
|
|
|
return {
|
|
message: `Equipo con inv ${inventario} eliminado correctamente`,
|
|
};
|
|
}
|
|
|
|
async buscarEquipos(filtros: any, page: number = 1, limit: number = 10) {
|
|
const query = this.equipoRepository
|
|
.createQueryBuilder('equipo')
|
|
.leftJoinAndSelect('equipo.marca', 'marca')
|
|
.leftJoinAndSelect('equipo.estado', 'estado')
|
|
.leftJoinAndSelect('equipo.adscripcion', 'adscripcion')
|
|
.leftJoinAndSelect('equipo.tipoEquipo', 'tipoEquipo')
|
|
.leftJoinAndSelect('equipo.sistemaOperativo', 'sistemaOperativo')
|
|
.leftJoinAndSelect('equipo.procesador', 'procesador')
|
|
.leftJoinAndSelect('equipo.tipoUso', 'tipoUso');
|
|
|
|
// Filtros dinámicos
|
|
if (filtros.inventario) {
|
|
query.andWhere('equipo.inventario LIKE :inventario', {
|
|
inventario: `%${filtros.inventario}%`,
|
|
});
|
|
}
|
|
|
|
if (filtros.tipoEquipo) {
|
|
query.andWhere('tipoEquipo.id = :tipoEquipo', {
|
|
tipoEquipo: filtros.tipoEquipo,
|
|
});
|
|
}
|
|
|
|
if (filtros.antiguedad) {
|
|
query.andWhere('equipo.antiguedad LIKE :antiguedad', {
|
|
antiguedad: `%${filtros.antiguedad}%`,
|
|
});
|
|
}
|
|
|
|
if (filtros.marca) {
|
|
query.andWhere('marca.id = :marca', { marca: filtros.marca });
|
|
}
|
|
|
|
if (filtros.estado) {
|
|
query.andWhere('estado.id = :estado', { estado: filtros.estado });
|
|
}
|
|
|
|
if (filtros.adscripcion) {
|
|
query.andWhere('adscripcion.id = :adscripcion', {
|
|
adscripcion: filtros.adscripcion,
|
|
});
|
|
}
|
|
|
|
if (filtros.tipoUso) {
|
|
query.andWhere('tipoUso.id = :tipoUso', { tipoUso: filtros.tipoUso });
|
|
}
|
|
|
|
if (filtros.procesador) {
|
|
query.andWhere('procesador.id = :procesador', {
|
|
procesador: filtros.procesador,
|
|
});
|
|
}
|
|
|
|
if (filtros.sistemaOperativo) {
|
|
query.andWhere('sistemaOperativo.id = :sistemaOperativo', {
|
|
sistemaOperativo: filtros.sistemaOperativo,
|
|
});
|
|
}
|
|
|
|
// Paginación
|
|
query.skip((page - 1) * limit).take(limit);
|
|
|
|
// Ejecutar consulta
|
|
const [data, total] = await query.getManyAndCount();
|
|
|
|
return {
|
|
total,
|
|
page,
|
|
limit,
|
|
data,
|
|
};
|
|
}
|
|
async updateEquipo(equipoNuevo: UpdateEquipoDto, id_equipo: number, id_user) {
|
|
let equipo = await this.equipoRepository.findOne({
|
|
where: { id_equipo },
|
|
relations: ['tipoEquipo'],
|
|
});
|
|
if (!equipo) {
|
|
throw new NotFoundException('No se encontó equipo');
|
|
}
|
|
|
|
const updateData = {
|
|
id_equipo,
|
|
lugar: equipoNuevo.lugar ? equipoNuevo.lugar : undefined,
|
|
serie: equipoNuevo.serie ? equipoNuevo.serie : undefined,
|
|
modelo: equipoNuevo.modelo ? equipoNuevo.modelo : undefined,
|
|
estado: equipoNuevo.id_estado
|
|
? { id_estado: equipoNuevo.id_estado }
|
|
: undefined,
|
|
adscripcion: equipoNuevo.id_adscripcion
|
|
? { id_adscripcion: equipoNuevo.id_adscripcion }
|
|
: undefined,
|
|
sistemaOperativo: equipoNuevo.id_sistema_operativo
|
|
? { id_sistema_operativo: equipoNuevo.id_sistema_operativo }
|
|
: undefined,
|
|
procesador: equipoNuevo.id_procesador
|
|
? { id_procesador: equipoNuevo.id_procesador }
|
|
: undefined,
|
|
tipoUso: equipoNuevo.id_tipo_uso
|
|
? { id_uso: equipoNuevo.id_tipo_uso }
|
|
: undefined,
|
|
marca: equipoNuevo.id_marca
|
|
? { id_marca: equipoNuevo.id_marca }
|
|
: undefined,
|
|
periferico: equipoNuevo.id_periferico
|
|
? { id_periferico: equipoNuevo.id_periferico }
|
|
: undefined,
|
|
laboratorio: equipoNuevo.id_laboratorio
|
|
? { id_laboratorio: equipoNuevo.id_laboratorio }
|
|
: undefined,
|
|
proyecto: equipoNuevo.id_proyecto
|
|
? { id_proyecto: equipoNuevo.id_proyecto }
|
|
: undefined,
|
|
};
|
|
|
|
const equipoUpdate = await this.equipoRepository.preload(updateData);
|
|
|
|
if (!equipoUpdate) {
|
|
throw new Error(`No se encontró el equipo con id ${id_equipo}`);
|
|
}
|
|
const mov = await this.movimiento.crear({
|
|
idUsuario: id_user,
|
|
idEquipo: id_equipo,
|
|
observaciones: equipoNuevo.observaciones,
|
|
});
|
|
return await this.equipoRepository.save(equipoUpdate);
|
|
}
|
|
|
|
async findEquipo(inventario: string) {
|
|
const equipo = await this.equipoRepository.findOne({
|
|
where: { inventario },
|
|
relations: [
|
|
'marca',
|
|
'estado',
|
|
'adscripcion',
|
|
'tipoEquipo',
|
|
'sistemaOperativo',
|
|
'procesador',
|
|
'tipoUso',
|
|
'periferico',
|
|
'proyecto',
|
|
'laboratorio',
|
|
],
|
|
});
|
|
|
|
if (!equipo) {
|
|
throw new NotFoundException(
|
|
`No se encontró el equipo con inventario ${inventario}`,
|
|
);
|
|
}
|
|
|
|
const responsable = await this.searchResponsable(
|
|
equipo.adscripcion.adscripcion,
|
|
);
|
|
|
|
const observaciones = await this.movimiento.buscar(equipo.id_equipo);
|
|
|
|
return { ...equipo, ...responsable, ...observaciones };
|
|
}
|
|
|
|
async searchResponsable(nombreAdscripcion: string) {
|
|
const adscripcion = await this.adscripcionRepo.findOneBy({
|
|
adscripcion: nombreAdscripcion,
|
|
});
|
|
if (!adscripcion) {
|
|
throw new Error(
|
|
`No se encontró la adscripción con nombre ${nombreAdscripcion}`,
|
|
);
|
|
}
|
|
let entrada = {
|
|
tipoBusqueda: 'area',
|
|
IdUnidadResponsable: adscripcion.id_adscripcion,
|
|
};
|
|
|
|
const url = process.env.API_FUNCIONARIOS;
|
|
|
|
if (!url) throw new Error('Url no definida en las variables de entorno');
|
|
|
|
const response = await axios.post(url, entrada);
|
|
return response.data;
|
|
}
|
|
|
|
async create(equipo: CreateEquipoDto, id_usuario: number) {
|
|
const equipoExistente = await this.equipoRepository.findOne({
|
|
where: { inventario: equipo.inventario },
|
|
});
|
|
if (equipoExistente) {
|
|
throw new BadRequestException('El equipo ya existe');
|
|
}
|
|
|
|
const datosBase = {
|
|
inventario: equipo.inventario,
|
|
serie: equipo.serie,
|
|
lugar: equipo.lugar,
|
|
fechaFactura: equipo.fechaFactura,
|
|
antiguedad: equipo.antiguedad,
|
|
modelo: equipo.modelo,
|
|
estado: { id_estado: equipo.id_estado },
|
|
adscripcion: { id_adscripcion: equipo.id_adscripcion },
|
|
tipoUso: { id_uso: equipo.id_uso },
|
|
marca: { id_marca: equipo.id_marca },
|
|
tipoEquipo: { id_tipo_de_equipo: equipo.id_tipo_equipo },
|
|
proyecto: { id_proyecto: equipo.id_proyecto },
|
|
laboratorio: { id_laboratorio: equipo.id_laboratorio },
|
|
};
|
|
|
|
const nuevoEquipo = this.equipoRepository.create(
|
|
equipo.isImpresora
|
|
? { ...datosBase, periferico: { id_periferico: equipo.id_periferico } }
|
|
: {
|
|
...datosBase,
|
|
sistemaOperativo: {
|
|
id_sistema_operativo: equipo.id_sistema_operativo,
|
|
},
|
|
procesador: { id_procesador: equipo.id_procesador },
|
|
},
|
|
);
|
|
|
|
let equip = await this.equipoRepository.save(nuevoEquipo);
|
|
|
|
if (!equip) throw new Error('No se creó el equipo');
|
|
|
|
// Crear movimiento asociado
|
|
await this.movimiento.crear({
|
|
idEquipo: equip.id_equipo,
|
|
idUsuario: id_usuario,
|
|
});
|
|
|
|
return equip;
|
|
}
|
|
|
|
async findAllUsos() {
|
|
return await this.usoRepo.find();
|
|
}
|
|
|
|
async findAllMarcas() {
|
|
return await this.marcaRepo.find();
|
|
}
|
|
|
|
async findAllEstados() {
|
|
return await this.estadoRepo.find();
|
|
}
|
|
|
|
async findAllProyectos() {
|
|
return await this.proyectoRepo.find();
|
|
}
|
|
|
|
async findAllLaboratorios() {
|
|
return await this.laboratorioRepo.find();
|
|
}
|
|
|
|
async findAllAdscripciones() {
|
|
return await this.adscripcionRepo.find();
|
|
}
|
|
|
|
async findAllTiposEquipo() {
|
|
return await this.tipoEquipoRepo.find();
|
|
}
|
|
|
|
async findAllSistemasOperativos() {
|
|
return await this.sistemaOperativoRepo.find();
|
|
}
|
|
|
|
async findAllProcesadores() {
|
|
return await this.procesadorRepo.find();
|
|
}
|
|
|
|
async findAllPerifericos() {
|
|
return await this.perifericoRepo.find();
|
|
}
|
|
|
|
async findAllProcesadorTipoEquipos() {
|
|
return await this.procesadorRepo.find();
|
|
}
|
|
|
|
// async createEcxel(res: Response) {
|
|
// const data = await this.generar_reporte();
|
|
// return this.exportarReporteAExcel(data, res);
|
|
// }
|
|
|
|
async createEcxel(res: Response) {
|
|
return await this.exportarEquiposAExcel(res);
|
|
}
|
|
@Cron('0 0 0 * * *')
|
|
async llenadoDeAntiguedad() {
|
|
const result = await this.equipoRepository
|
|
.createQueryBuilder()
|
|
.update(Equipo)
|
|
.set({
|
|
antiguedad: () => `
|
|
CASE
|
|
WHEN fecha_factura IS NULL THEN 'SINFECHA'
|
|
WHEN TIMESTAMPDIFF(YEAR, fecha_factura, CURDATE()) < 2 THEN 'MENORES DE 2'
|
|
WHEN TIMESTAMPDIFF(YEAR, fecha_factura, CURDATE()) BETWEEN 2 AND 3 THEN 'ENTRE 2 Y 3'
|
|
WHEN TIMESTAMPDIFF(YEAR, fecha_factura, CURDATE()) BETWEEN 4 AND 5 THEN 'ENTRE 4 Y 5'
|
|
WHEN TIMESTAMPDIFF(YEAR, fecha_factura, CURDATE()) >= 6 THEN 'ENTRE 6 Y MAYORES'
|
|
END
|
|
`,
|
|
})
|
|
.execute();
|
|
|
|
return result;
|
|
}
|
|
|
|
async exportarEquiposAExcel(res: Response) {
|
|
const workbook = new ExcelJS.Workbook();
|
|
const sheet = workbook.addWorksheet('Equipos');
|
|
|
|
// =====================================
|
|
// ✅ ENCABEZADOS
|
|
// =====================================
|
|
sheet.columns = [
|
|
{ header: 'Inventario', key: 'inventario', width: 70 },
|
|
{ header: 'Serie', key: 'serie', width: 70 },
|
|
{ header: 'Lugar', key: 'lugar', width: 70 },
|
|
{ header: 'Fecha Factura', key: 'fechaFactura', width: 70 },
|
|
{ header: 'Antigüedad', key: 'antiguedad', width: 70 },
|
|
{ header: 'Modelo', key: 'modelo', width: 70 },
|
|
{ header: 'Marca', key: 'marca', width: 70 },
|
|
{ header: 'Estado', key: 'estado', width: 70 },
|
|
{ header: 'Adscripción', key: 'adscripcion', width: 70 },
|
|
{ header: 'Tipo de Equipo', key: 'tipoEquipo', width: 70 },
|
|
{ header: 'Sistema Operativo', key: 'sistemaOperativo', width: 70 },
|
|
{ header: 'Procesador', key: 'procesador', width: 70 },
|
|
{ header: 'Tipo de Uso', key: 'tipoUso', width: 70 },
|
|
{ header: 'Periférico', key: 'periferico', width: 70 },
|
|
{ header: 'Proyecto', key: 'proyecto', width: 70 },
|
|
{ header: 'Laboratorio', key: 'laboratorio', width: 70 },
|
|
{ header: 'Observaciones', key: 'observaciones', width: 100 },
|
|
{ header: 'Fecha Movimiento', key: 'fechaMovimiento', width: 70 },
|
|
{ header: 'Usuario', key: 'user', width: 70 },
|
|
];
|
|
|
|
// =====================================
|
|
// ✅ OBTENER EQUIPOS
|
|
// =====================================
|
|
const equipos = await this.equipoRepository.find({
|
|
relations: [
|
|
'marca',
|
|
'estado',
|
|
'adscripcion',
|
|
'tipoEquipo',
|
|
'sistemaOperativo',
|
|
'procesador',
|
|
'tipoUso',
|
|
'periferico',
|
|
'proyecto',
|
|
'laboratorio',
|
|
],
|
|
});
|
|
|
|
// =====================================
|
|
// ✅ LLENAR FILAS
|
|
// =====================================
|
|
for (const equipo of equipos) {
|
|
const movimiento = await this.movimiento.buscar(equipo.id_equipo);
|
|
|
|
sheet.addRow({
|
|
inventario: equipo.inventario,
|
|
serie: equipo.serie,
|
|
lugar: equipo.lugar,
|
|
fechaFactura: equipo.fechaFactura,
|
|
antiguedad: equipo.antiguedad,
|
|
modelo: equipo.modelo,
|
|
marca: equipo.marca?.marca ?? '',
|
|
estado: equipo.estado?.estado ?? '',
|
|
adscripcion: equipo.adscripcion?.adscripcion ?? '',
|
|
tipoEquipo: equipo.tipoEquipo?.tipo_equipo ?? '',
|
|
sistemaOperativo: equipo.sistemaOperativo?.sistema_operativo ?? '',
|
|
procesador: equipo.procesador?.procesador ?? '',
|
|
tipoUso: equipo.tipoUso?.tipo_uso ?? '',
|
|
periferico: equipo.periferico?.periferico ?? '',
|
|
proyecto: equipo.proyecto?.proyecto ?? '',
|
|
laboratorio: equipo.laboratorio?.laboratorio ?? '',
|
|
observaciones: movimiento?.observaciones ?? '',
|
|
fechaMovimiento: movimiento?.fechaMovimiento ?? '',
|
|
user: movimiento?.user?.nombre ?? '',
|
|
});
|
|
}
|
|
|
|
// =====================================
|
|
// ✅ ESTILO HEADER
|
|
// =====================================
|
|
sheet.getRow(1).font = { bold: true };
|
|
|
|
// =====================================
|
|
// ✅ RESPUESTA AL NAVEGADOR
|
|
// =====================================
|
|
res.setHeader(
|
|
'Content-Type',
|
|
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
|
);
|
|
|
|
res.setHeader('Content-Disposition', 'attachment; filename=equipos.xlsx');
|
|
|
|
await workbook.xlsx.write(res);
|
|
res.end();
|
|
}
|
|
|
|
async exportarReporteAExcel(data: any, res: Response) {
|
|
const workbook = new ExcelJS.Workbook();
|
|
let count = 1;
|
|
|
|
for (const key of Object.keys(data)) {
|
|
let sheetName = key.substring(0, 30);
|
|
|
|
if (workbook.getWorksheet(sheetName)) {
|
|
sheetName = `${sheetName}_${count++}`;
|
|
}
|
|
|
|
const sheet = workbook.addWorksheet(sheetName);
|
|
|
|
const rows = data[key];
|
|
|
|
if (!Array.isArray(rows) || rows.length === 0) {
|
|
sheet.addRow([`(sin datos)`]);
|
|
continue;
|
|
}
|
|
|
|
const headers = Object.keys(rows[0]);
|
|
|
|
sheet.addRow(headers);
|
|
|
|
for (const row of rows) {
|
|
sheet.addRow(headers.map((h) => row[h]));
|
|
}
|
|
|
|
sheet.getRow(1).font = { bold: true };
|
|
sheet.getRow(1).alignment = { horizontal: 'center' };
|
|
sheet.columns.forEach((col) => (col.width = 35));
|
|
}
|
|
|
|
res.setHeader(
|
|
'Content-Type',
|
|
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
|
);
|
|
|
|
res.setHeader('Content-Disposition', 'attachment; filename=reporte.xlsx');
|
|
|
|
await workbook.xlsx.write(res);
|
|
res.status(200).end();
|
|
}
|
|
|
|
async createReport() {
|
|
let obj = await this.generar_reporte();
|
|
const objectParse = Array.isArray(obj)
|
|
? obj.map((item) => this.flattenObject(item))
|
|
: [this.flattenObject(obj)];
|
|
return objectParse;
|
|
}
|
|
|
|
async contar_tipoEquipos_tipoUso(estado: string[]): Promise<any> {
|
|
try {
|
|
const result = await this.equipoRepository
|
|
.createQueryBuilder('e')
|
|
.innerJoin('e.tipoEquipo', 't')
|
|
.innerJoin('e.tipoUso', 'u')
|
|
.innerJoin('e.sistemaOperativo', 'so')
|
|
.innerJoin('e.estado', 'es')
|
|
.select([
|
|
't.tipo_equipo AS tipo_equipo',
|
|
'u.tipo_uso AS tipo_uso',
|
|
'so.sistema_operativo AS sistema_operativo',
|
|
])
|
|
.addSelect('COUNT(*) AS total')
|
|
.where('es.estado IN (:...estado)', { estado })
|
|
.groupBy('t.id_tipo_de_equipo')
|
|
.addGroupBy('u.id_uso')
|
|
.addGroupBy('so.id_sistema_operativo')
|
|
.getRawMany();
|
|
|
|
return result;
|
|
} catch (error) {
|
|
console.error('Error al contar equipos por tipo, uso y SO:', error);
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
async contar_tipoEquipos_sistemasOperativos(
|
|
tipo_equipo: string[],
|
|
estado: string[],
|
|
): Promise<any> {
|
|
try {
|
|
const count = await this.equipoRepository
|
|
.createQueryBuilder('e')
|
|
.innerJoin('e.tipoEquipo', 't')
|
|
.innerJoin('e.sistemaOperativo', 's')
|
|
.innerJoin('e.estado', 'es')
|
|
.where('t.tipo_equipo IN (:...tipo_equipo)', { tipo_equipo })
|
|
.andWhere('es.estado IN (:...estado)', { estado })
|
|
.select(['s.sistema_operativo AS sistema_operativo'])
|
|
.addSelect('COUNT(*) AS total')
|
|
.groupBy('s.sistema_operativo')
|
|
.getRawMany();
|
|
|
|
return count;
|
|
} catch (error) {
|
|
console.error('Error al contar equipos por tipo y uso:', error);
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
async contar_tipoEquipos_procesador(
|
|
tipo_equipo: string[],
|
|
estado: string[],
|
|
): Promise<any> {
|
|
try {
|
|
const count = await this.equipoRepository
|
|
.createQueryBuilder('e')
|
|
.innerJoin('e.procesador', 'p')
|
|
.innerJoin('e.tipoEquipo', 't')
|
|
.innerJoin('e.tipoUso', 'u')
|
|
.innerJoin('e.estado', 'es')
|
|
.where('t.tipo_equipo IN (:...tipo_equipo)', { tipo_equipo })
|
|
.andWhere('es.estado IN (:...estado)', { estado })
|
|
.select(['p.procesador AS procesador', 'u.tipo_uso AS uso'])
|
|
.addSelect('COUNT(*) AS total')
|
|
.groupBy('p.procesador')
|
|
.addGroupBy('u.tipo_uso')
|
|
.getRawMany();
|
|
|
|
return count;
|
|
} catch (error) {
|
|
console.error('Error al contar equipos por tipo y uso:', error);
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
async contar_tipoEquipos(
|
|
tipo_equipo: string[],
|
|
estado: string[],
|
|
): Promise<any> {
|
|
try {
|
|
const count = await this.equipoRepository
|
|
.createQueryBuilder('e')
|
|
.innerJoin('e.tipoEquipo', 't')
|
|
.innerJoin('e.estado', 'es')
|
|
.where('t.tipo_equipo IN (:...tipo_equipo)', { tipo_equipo })
|
|
.andWhere('es.estado IN (:...estado)', { estado })
|
|
.select('COUNT(*) AS total')
|
|
.getRawOne();
|
|
|
|
return count;
|
|
} catch (error) {
|
|
console.error('Error al contar equipos por tipo y uso:', error);
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
async contar_tipoEquipos_antiguedad(estado: string[]): Promise<any> {
|
|
const totalEscrtitorio = await this.contar_tipoEquipos(escritorio, estado);
|
|
const totalPortatiles = await this.contar_tipoEquipos(portatil, estado);
|
|
const totalAltoRendimiento = await this.contar_tipoEquipos(
|
|
['SERVIDOR'],
|
|
estado,
|
|
);
|
|
try {
|
|
const countEscritorios = await this.equipoRepository
|
|
.createQueryBuilder('e')
|
|
.innerJoin('e.tipoEquipo', 't')
|
|
.innerJoin('e.estado', 'es')
|
|
.where('t.tipo_equipo IN (:...tipo_equipo)', {
|
|
tipo_equipo: escritorio,
|
|
})
|
|
.select(['e.antiguedad AS antiguedad'])
|
|
.andWhere('es.estado IN (:...estado)', { estado })
|
|
.addSelect('COUNT(*) AS total')
|
|
.groupBy('e.antiguedad')
|
|
.getRawMany();
|
|
const countPortatiles = await this.equipoRepository
|
|
.createQueryBuilder('e')
|
|
.innerJoin('e.tipoEquipo', 't')
|
|
.innerJoin('e.estado', 'es')
|
|
.where('t.tipo_equipo IN (:...tipo_equipo)', {
|
|
tipo_equipo: portatil,
|
|
})
|
|
.andWhere('es.estado IN (:...estado)', { estado })
|
|
.select(['e.antiguedad AS antiguedad'])
|
|
.addSelect('COUNT(*) AS total')
|
|
.groupBy('e.antiguedad')
|
|
.getRawMany();
|
|
const countAltoRendimiento = await this.equipoRepository
|
|
.createQueryBuilder('e')
|
|
.innerJoin('e.tipoEquipo', 't')
|
|
.innerJoin('e.estado', 'es')
|
|
.where('t.tipo_equipo IN (:...tipo_equipo)', {
|
|
tipo_equipo: ['SERVIDOR'],
|
|
})
|
|
.andWhere('es.estado IN (:...estado)', { estado })
|
|
.select(['e.antiguedad AS antiguedad'])
|
|
.addSelect('COUNT(*) AS total')
|
|
.groupBy('e.antiguedad')
|
|
.getRawMany();
|
|
|
|
return {
|
|
escritorios: countEscritorios.map((i) => ({
|
|
antiguedad: i.antiguedad,
|
|
total: i.total,
|
|
porcentaje: ((i.total / totalEscrtitorio.total) * 100).toFixed(30),
|
|
})),
|
|
portatiles: countPortatiles.map((i) => ({
|
|
antiguedad: i.antiguedad,
|
|
total: i.total,
|
|
porcentaje: ((i.total / totalPortatiles.total) * 100).toFixed(30),
|
|
})),
|
|
altoRendimiento: countAltoRendimiento.map((i) => ({
|
|
antiguedad: i.antiguedad,
|
|
total: i.total,
|
|
porcentaje: ((i.total / totalAltoRendimiento.total) * 100).toFixed(
|
|
30,
|
|
),
|
|
})),
|
|
};
|
|
} catch (error) {
|
|
console.error('Error al contar equipos por tipo y uso:', error);
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
async garantia(tipo_equipo: string[], estado: string[]): Promise<any> {
|
|
try {
|
|
const count = await this.equipoRepository
|
|
.createQueryBuilder('e')
|
|
.innerJoin('e.tipoEquipo', 't')
|
|
.innerJoin('e.estado', 'es')
|
|
.where('e.fechaFactura >= DATE_SUB(CURDATE(), INTERVAL 3 YEAR)')
|
|
.andWhere('t.tipo_equipo IN (:...tipo_equipo)', { tipo_equipo })
|
|
.andWhere('es.estado IN (:...estado)', { estado })
|
|
.getCount();
|
|
|
|
return count;
|
|
} catch (error) {
|
|
console.error('Error al contar equipos por tipo y uso:', error);
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
async equipos_impesion(
|
|
perifericos: string[],
|
|
estado: string[],
|
|
): Promise<any> {
|
|
try {
|
|
const count = await this.equipoRepository
|
|
.createQueryBuilder('e')
|
|
.innerJoin('e.periferico', 'p')
|
|
.innerJoin('e.estado', 'es')
|
|
.select(['p.periferico AS periferico'])
|
|
.where('p.periferico IN (:...perifericos)', { perifericos })
|
|
.andWhere('es.estado IN (:...estado)', { estado })
|
|
.getCount();
|
|
|
|
return count;
|
|
} catch (error) {
|
|
console.error('Error al contar equipos por tipo y uso:', error);
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
async equipos_impesion_group(
|
|
perifericos: string[],
|
|
estado: string[],
|
|
): Promise<any> {
|
|
try {
|
|
const count = await this.equipoRepository
|
|
.createQueryBuilder('e')
|
|
.innerJoin('e.periferico', 'p')
|
|
.innerJoin('e.estado', 'es')
|
|
.where('p.periferico IN (:...perifericos)', { perifericos })
|
|
.andWhere('es.estado IN (:...estado)', { estado })
|
|
.select('p.periferico AS periferico')
|
|
.addSelect('COUNT(*) AS total')
|
|
.groupBy('p.periferico')
|
|
.getRawMany();
|
|
|
|
return count;
|
|
} catch (error) {
|
|
console.error('Error al contar equipos por tipo y uso:', error);
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
async contar_periferico_tipoUso(
|
|
perifericos: string[],
|
|
estado: string[],
|
|
): Promise<any> {
|
|
try {
|
|
const count = await this.equipoRepository
|
|
.createQueryBuilder('e')
|
|
.innerJoin('e.tipoUso', 't')
|
|
.innerJoin('e.periferico', 'p')
|
|
.innerJoin('e.estado', 'es')
|
|
.where('p.periferico IN (:...perifericos)', { perifericos })
|
|
.andWhere('es.estado IN (:...estado)', { estado })
|
|
.select(['t.tipo_uso AS uso'])
|
|
.addSelect('COUNT(*) AS total')
|
|
.groupBy('t.tipo_uso')
|
|
.getRawMany();
|
|
|
|
return count;
|
|
} catch (error) {
|
|
console.error('Error al contar equipos por tipo y uso:', error);
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
async contar_perifericos_antiguedad(
|
|
impresion: string[],
|
|
digitalizacion: string[],
|
|
estado: string[],
|
|
): Promise<{
|
|
impresion: { antiguedad: any; total: number; porcentaje: string }[];
|
|
digitalizacion: { antiguedad: any; total: number; porcentaje: string }[];
|
|
}> {
|
|
try {
|
|
// Helper para obtener total por tipos de equipo (count simple, sin group by)
|
|
const getTotalPorTipos = async (tipos: string[]): Promise<any> => {
|
|
if (!tipos || tipos.length === 0) return 0;
|
|
return this.equipoRepository
|
|
.createQueryBuilder('e')
|
|
.innerJoin('e.periferico', 'p')
|
|
.innerJoin('e.estado', 'es')
|
|
.where('p.periferico IN (:...tipos)', { tipos })
|
|
.andWhere('es.estado IN (:...estado)', { estado })
|
|
.select('COUNT(*) AS total')
|
|
.getRawOne();
|
|
};
|
|
|
|
// Ejecutar ambos totales en paralelo
|
|
|
|
const [totalI, totalD] = await Promise.all([
|
|
getTotalPorTipos(impresion),
|
|
getTotalPorTipos(digitalizacion),
|
|
]);
|
|
const totalImpresion = totalI.total;
|
|
|
|
const totalDigitalizacion = totalD.total;
|
|
|
|
// Obtener conteos por antiguedad para impresion
|
|
const countImpresionPromise = this.equipoRepository
|
|
.createQueryBuilder('e')
|
|
.innerJoin('e.periferico', 'p')
|
|
.innerJoin('e.tipoEquipo', 't')
|
|
.innerJoin('e.estado', 'es')
|
|
.where('p.periferico IN (:...periferico)', { periferico: impresion })
|
|
.andWhere('es.estado IN (:...estado)', { estado })
|
|
.select(['e.antiguedad AS antiguedad'])
|
|
.addSelect('COUNT(e.id_equipo) AS total')
|
|
.groupBy('e.antiguedad')
|
|
.getRawMany();
|
|
|
|
// Obtener conteos por antiguedad para digitalizacion
|
|
const countDigitalizacionPromise = this.equipoRepository
|
|
.createQueryBuilder('e')
|
|
.innerJoin('e.periferico', 'p')
|
|
.innerJoin('e.tipoEquipo', 't')
|
|
.innerJoin('e.estado', 'es')
|
|
.where('p.periferico IN (:...periferico)', {
|
|
periferico: digitalizacion,
|
|
})
|
|
.andWhere('es.estado IN (:...estado)', { estado })
|
|
.select(['e.antiguedad AS antiguedad'])
|
|
.addSelect('COUNT(e.id_equipo) AS total')
|
|
.groupBy('e.antiguedad')
|
|
.getRawMany();
|
|
|
|
// Ejecutar ambas consultas en paralelo
|
|
const [countImpresion, countDigitalizacion] = await Promise.all([
|
|
countImpresionPromise,
|
|
countDigitalizacionPromise,
|
|
]);
|
|
|
|
// Tipo para salida
|
|
interface Porcentaje {
|
|
antiguedad: any;
|
|
total: number;
|
|
porcentaje: string;
|
|
}
|
|
|
|
// Mapear resultados calculando porcentajes (evitar async dentro de map/forEach)
|
|
const porcentajesImpresion: Porcentaje[] = countImpresion.map((item) => {
|
|
const total = Number(item.total) || 0;
|
|
const porcentaje =
|
|
totalImpresion > 0
|
|
? ((total / totalImpresion) * 100).toFixed(30)
|
|
: '0.00';
|
|
return {
|
|
antiguedad: item.antiguedad,
|
|
total,
|
|
porcentaje,
|
|
};
|
|
});
|
|
|
|
const porcentajesDigitalizacion: Porcentaje[] = countDigitalizacion.map(
|
|
(item) => {
|
|
const total = Number(item.total) || 0;
|
|
const porcentaje =
|
|
totalDigitalizacion > 0
|
|
? ((total / totalDigitalizacion) * 100).toFixed(30)
|
|
: '0.00';
|
|
return {
|
|
antiguedad: item.antiguedad,
|
|
total,
|
|
porcentaje,
|
|
};
|
|
},
|
|
);
|
|
|
|
return {
|
|
impresion: porcentajesImpresion,
|
|
digitalizacion: porcentajesDigitalizacion,
|
|
};
|
|
} catch (error) {
|
|
console.error('Error en contar_perifericos_antiguedad:', error);
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
async proyecto_equipos(estado: string[]) {
|
|
try {
|
|
const count = await this.equipoRepository
|
|
.createQueryBuilder('e')
|
|
.innerJoin('e.proyecto', 'p')
|
|
.innerJoin('e.estado', 'es')
|
|
.select(['p.proyecto AS proyecto'])
|
|
.andWhere('es.estado IN (:...estado)', { estado })
|
|
.addSelect('COUNT(*) AS total')
|
|
.groupBy('p.proyecto')
|
|
.getRawMany();
|
|
|
|
return count;
|
|
} catch (error) {
|
|
console.error('Error al contar equipos proyectos:', error);
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
async laboratorio_equipos(estado: string[]) {
|
|
try {
|
|
const count = await this.equipoRepository
|
|
.createQueryBuilder('e')
|
|
.innerJoin('e.laboratorio', 'l')
|
|
.innerJoin('e.estado', 'es')
|
|
.select(['l.laboratorio AS laboratorio'])
|
|
.andWhere('es.estado IN (:...estado)', { estado })
|
|
.addSelect('COUNT(*) AS total')
|
|
.groupBy('l.laboratorio')
|
|
.getRawMany();
|
|
|
|
return count;
|
|
} catch (error) {
|
|
console.error('Error al contar equipos proyectos:', error);
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
async generar_reporte(estado: string[] = estado_excluidos) {
|
|
const [
|
|
contar_equipos_de_tipo_uso,
|
|
sisitema_operativo_pc,
|
|
sisitema_operativo_mac,
|
|
sisitema_operativo_portatiles_pc,
|
|
sisitema_operativo_portatiles_mac,
|
|
sisitema_operativo_servidores,
|
|
contar_pc_procesador,
|
|
contar_mac_procesador,
|
|
contar_portatil_procesador,
|
|
contar_portatil_mac_procesador,
|
|
contar_servidor_procesador,
|
|
porcentaje_antiguedad,
|
|
garantia_escritorio,
|
|
garantia_portatiles,
|
|
garantia_servidor,
|
|
contar_impresoras,
|
|
contar_impresoras_tipo_uso,
|
|
contar_digitalizacion,
|
|
contar_contar_digitalizacion_u,
|
|
contar_perifericos_antiguedad,
|
|
cotar_laboratorios,
|
|
contar_proyectos,
|
|
] = await Promise.all([
|
|
this.contar_tipoEquipos_tipoUso(estado),
|
|
this.contar_tipoEquipos_sistemasOperativos(equpos_pc, estado),
|
|
this.contar_tipoEquipos_sistemasOperativos([estritorio_mac], estado),
|
|
this.contar_tipoEquipos_sistemasOperativos(portatiles, estado),
|
|
this.contar_tipoEquipos_sistemasOperativos([portatiles_mac], estado),
|
|
this.contar_tipoEquipos_sistemasOperativos([servidor], estado),
|
|
this.contar_tipoEquipos_procesador(equpos_pc, estado),
|
|
this.contar_tipoEquipos_procesador([estritorio_mac], estado),
|
|
this.contar_tipoEquipos_procesador(portatiles, estado),
|
|
this.contar_tipoEquipos_procesador([portatiles_mac], estado),
|
|
this.contar_tipoEquipos_procesador([servidor], estado),
|
|
this.contar_tipoEquipos_antiguedad(estado),
|
|
this.garantia(escritorio, estado),
|
|
this.garantia(portatil, estado),
|
|
this.garantia([servidor], estado),
|
|
this.equipos_impesion_group(impresoras, estado),
|
|
this.contar_periferico_tipoUso(impresoras, estado),
|
|
this.equipos_impesion_group(dijitales, estado),
|
|
this.contar_periferico_tipoUso(dijitales, estado),
|
|
this.contar_perifericos_antiguedad(impresoras, dijitales, estado),
|
|
this.proyecto_equipos(estado),
|
|
this.laboratorio_equipos(estado),
|
|
]);
|
|
|
|
return {
|
|
contar_equipos_de_tipo_uso,
|
|
sisitema_operativo_pc,
|
|
sisitema_operativo_mac,
|
|
sisitema_operativo_portatiles_pc,
|
|
sisitema_operativo_portatiles_mac,
|
|
sisitema_operativo_servidores,
|
|
contar_pc_procesador,
|
|
contar_mac_procesador,
|
|
contar_portatil_procesador,
|
|
contar_portatil_mac_procesador,
|
|
contar_servidor_procesador,
|
|
porcentaje_antiguedad,
|
|
garantia_escritorio,
|
|
garantia_portatiles,
|
|
garantia_servidor,
|
|
contar_impresoras,
|
|
contar_impresoras_tipo_uso,
|
|
contar_digitalizacion,
|
|
contar_contar_digitalizacion_u,
|
|
contar_perifericos_antiguedad,
|
|
cotar_laboratorios,
|
|
contar_proyectos,
|
|
};
|
|
}
|
|
|
|
async exportToClient(data: any, res: Response) {
|
|
// Aseguramos que los datos sean un arreglo de objetos planos
|
|
const rows = Array.isArray(data)
|
|
? data.map((item) => this.flattenObject(item))
|
|
: [this.flattenObject(data)];
|
|
|
|
// Crear workbook y hoja
|
|
const workbook = new ExcelJS.Workbook();
|
|
const worksheet = workbook.addWorksheet('Datos');
|
|
|
|
// Definir encabezados dinámicamente
|
|
const headers = Object.keys(rows[0] || {});
|
|
worksheet.columns = headers.map((h) => ({
|
|
header: h,
|
|
key: h,
|
|
width: 25,
|
|
}));
|
|
|
|
// Agregar filas
|
|
worksheet.addRows(rows);
|
|
|
|
// Estilizar encabezados
|
|
const headerRow = worksheet.getRow(1);
|
|
headerRow.font = { bold: true };
|
|
headerRow.alignment = { vertical: 'middle', horizontal: 'center' };
|
|
headerRow.eachCell((cell) => {
|
|
cell.border = {
|
|
top: { style: 'thin' },
|
|
left: { style: 'thin' },
|
|
bottom: { style: 'thin' },
|
|
right: { style: 'thin' },
|
|
};
|
|
});
|
|
|
|
// Configurar cabeceras HTTP
|
|
res.setHeader(
|
|
'Content-Type',
|
|
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
|
);
|
|
res.setHeader('Content-Disposition', 'attachment; filename="reporte.xlsx"');
|
|
|
|
// Enviar directamente al cliente
|
|
await workbook.xlsx.write(res);
|
|
res.end();
|
|
}
|
|
|
|
private flattenObject(obj: any, parentKey = '', res: any = {}): any {
|
|
for (const key of Object.keys(obj || {})) {
|
|
const propName = parentKey ? `${parentKey}.${key}` : key;
|
|
const value = obj[key];
|
|
|
|
if (value && typeof value === 'object' && !Array.isArray(value)) {
|
|
this.flattenObject(value, propName, res);
|
|
} else if (Array.isArray(value)) {
|
|
res[propName] = JSON.stringify(value);
|
|
} else {
|
|
res[propName] = value;
|
|
}
|
|
}
|
|
return res;
|
|
}
|
|
|
|
async ranking(year: number) {
|
|
const equipos = await this.equipoRepository.find({
|
|
relations: ['mov', 'mov.user'],
|
|
});
|
|
|
|
const conteo = new Map<
|
|
number,
|
|
{ id_usuario: number; nombre: string; total: number }
|
|
>();
|
|
|
|
for (const equipo of equipos) {
|
|
if (!equipo.mov || equipo.mov.length === 0) continue;
|
|
|
|
const equipoyear = equipo.mov.filter((mov) => {
|
|
const fecha = new Date(mov.fechaMovimiento);
|
|
return fecha.getFullYear() === year;
|
|
});
|
|
|
|
if (equipoyear.length === 0) continue;
|
|
|
|
const ultimoMov = equipoyear.sort(
|
|
(a, b) =>
|
|
new Date(b.fechaMovimiento).getTime() -
|
|
new Date(a.fechaMovimiento).getTime(),
|
|
)[0];
|
|
|
|
const user = ultimoMov.user;
|
|
if (!user) continue;
|
|
|
|
if (!conteo.has(user.id_usuario)) {
|
|
conteo.set(user.id_usuario, {
|
|
id_usuario: user.id_usuario,
|
|
nombre: user.nombre,
|
|
total: 0,
|
|
});
|
|
}
|
|
|
|
conteo.get(user.id_usuario)!.total++;
|
|
}
|
|
|
|
return Array.from(conteo.values()).sort((a, b) => b.total - a.total);
|
|
}
|
|
|
|
async grafica(
|
|
tipo: 'antiguedad' | 'uso' | 'so' | 'procesador',
|
|
filtros?: FiltrosGraficaDto
|
|
) {
|
|
|
|
const qb = this.equipoRepository
|
|
.createQueryBuilder('equipo')
|
|
.leftJoin('equipo.adscripcion', 'adscripcion')
|
|
.leftJoin('equipo.procesador', 'procesador')
|
|
.leftJoin('equipo.sistemaOperativo', 'sistemaOperativo')
|
|
.leftJoin('equipo.tipoUso', 'tipoUso')
|
|
|
|
// filtros
|
|
.andWhere('equipo.id_periferico IS NULL')
|
|
if (filtros?.adscripciones?.length) {
|
|
qb.andWhere('adscripcion.id_adscripcion IN (:...adscripciones)', {
|
|
adscripciones: filtros.adscripciones
|
|
})
|
|
.addSelect('adscripcion.adscripcion', 'adscripcion')
|
|
.groupBy('equipo.adscripcion')
|
|
|
|
}
|
|
|
|
if (filtros?.procesadores?.length) {
|
|
qb.andWhere('procesador.id_procesador IN (:...procesadores)', {
|
|
procesadores: filtros.procesadores
|
|
})
|
|
}
|
|
|
|
if (filtros?.sistemas?.length) {
|
|
qb.andWhere('sistemaOperativo.id_sistema_operativo IN (:...sistemas)', {
|
|
sistemas: filtros.sistemas
|
|
})
|
|
}
|
|
|
|
if (filtros?.usos?.length) {
|
|
qb.andWhere('tipoUso.id_uso IN (:...usos)', {
|
|
usos: filtros.usos
|
|
})
|
|
}
|
|
|
|
if (filtros?.antiguedad?.length && !filtros.antiguedad.includes("Todos")) {
|
|
qb.andWhere('equipo.antiguedad IN (:...antiguedad)', {
|
|
antiguedad: filtros.antiguedad
|
|
})
|
|
}
|
|
|
|
// selector dinámico
|
|
|
|
switch (tipo) {
|
|
|
|
case 'antiguedad':
|
|
|
|
qb.select('equipo.antiguedad', 'antiguedad')
|
|
.addSelect('COUNT(*)', 'total')
|
|
|
|
if (filtros?.adscripciones?.length) {
|
|
|
|
qb.addSelect('adscripcion.adscripcion', 'adscripcion')
|
|
|
|
qb.groupBy('equipo.antiguedad')
|
|
.addGroupBy('adscripcion.adscripcion')
|
|
|
|
} else {
|
|
|
|
qb.groupBy('equipo.antiguedad')
|
|
|
|
}
|
|
|
|
qb.orderBy(`
|
|
CASE
|
|
WHEN equipo.antiguedad = 'Menor a 2 años' THEN 1
|
|
WHEN equipo.antiguedad = 'Entre 2 y 3 años' THEN 2
|
|
WHEN equipo.antiguedad = 'Entre 4 y 5 años' THEN 3
|
|
WHEN equipo.antiguedad = 'Mayor a 6 años' THEN 4
|
|
END
|
|
`)
|
|
|
|
break
|
|
|
|
case 'uso':
|
|
|
|
qb.select('tipoUso.tipo_uso', 'uso')
|
|
.addSelect('COUNT(*)', 'total')
|
|
|
|
if (filtros?.adscripciones?.length) {
|
|
|
|
qb.addSelect('adscripcion.adscripcion', 'adscripcion')
|
|
|
|
qb.groupBy('tipoUso.tipo_uso')
|
|
.addGroupBy('adscripcion.adscripcion')
|
|
|
|
} else {
|
|
|
|
qb.groupBy('tipoUso.tipo_uso')
|
|
|
|
}
|
|
|
|
qb.orderBy(`
|
|
CASE
|
|
WHEN tipoUso.tipo_uso = 'ALUMNO' THEN 1
|
|
WHEN tipoUso.tipo_uso = 'PROFESOR' THEN 2
|
|
WHEN tipoUso.tipo_uso = 'ADMINISTRATIVO' THEN 3
|
|
WHEN tipoUso.tipo_uso = 'TÉCNICO ACADEMICO' THEN 4
|
|
END`)
|
|
|
|
break
|
|
|
|
case 'so':
|
|
|
|
qb.select('sistemaOperativo.sistema_operativo', 'so')
|
|
.addSelect('COUNT(*)', 'total')
|
|
|
|
if (filtros?.adscripciones?.length) {
|
|
|
|
qb.addSelect('adscripcion.adscripcion', 'adscripcion')
|
|
|
|
qb.groupBy('sistemaOperativo.sistema_operativo')
|
|
.addGroupBy('adscripcion.adscripcion')
|
|
|
|
} else {
|
|
|
|
qb.groupBy('sistemaOperativo.sistema_operativo')
|
|
|
|
}
|
|
qb.orderBy(`equipo.adscripcion`, "ASC")
|
|
|
|
break
|
|
|
|
case 'procesador':
|
|
|
|
qb.select('procesador.procesador', 'procesador')
|
|
.addSelect('COUNT(*)', 'total')
|
|
|
|
if (filtros?.adscripciones?.length) {
|
|
|
|
qb.addSelect('adscripcion.adscripcion', 'adscripcion')
|
|
|
|
qb.groupBy('procesador.procesador')
|
|
.addGroupBy('adscripcion.adscripcion')
|
|
|
|
} else {
|
|
|
|
qb.groupBy('procesador.procesador')
|
|
|
|
}
|
|
qb.orderBy(`equipo.adscripcion`, "ASC")
|
|
|
|
break
|
|
|
|
}
|
|
return qb.getRawMany()
|
|
|
|
}
|
|
|
|
async graficaPerifericos(
|
|
tipo: 'antiguedad' | 'uso' | 'so' | 'procesador',
|
|
filtros?: FiltrosGraficaDto
|
|
) {
|
|
|
|
const qb = this.equipoRepository
|
|
.createQueryBuilder('equipo')
|
|
.leftJoin('equipo.adscripcion', 'adscripcion')
|
|
.leftJoin('equipo.procesador', 'procesador')
|
|
.leftJoin('equipo.sistemaOperativo', 'sistemaOperativo')
|
|
.leftJoin('equipo.tipoUso', 'tipoUso')
|
|
|
|
// filtros
|
|
.andWhere('equipo.id_periferico IS NOT NULL')
|
|
if (filtros?.adscripciones?.length) {
|
|
qb.andWhere('adscripcion.id_adscripcion IN (:...adscripciones)', {
|
|
adscripciones: filtros.adscripciones
|
|
})
|
|
.addSelect('adscripcion.adscripcion', 'adscripcion')
|
|
.groupBy('equipo.adscripcion')
|
|
|
|
}
|
|
|
|
if (filtros?.procesadores?.length) {
|
|
qb.andWhere('procesador.id_procesador IN (:...procesadores)', {
|
|
procesadores: filtros.procesadores
|
|
})
|
|
}
|
|
|
|
if (filtros?.sistemas?.length) {
|
|
qb.andWhere('sistemaOperativo.id_sistema_operativo IN (:...sistemas)', {
|
|
sistemas: filtros.sistemas
|
|
})
|
|
}
|
|
|
|
if (filtros?.usos?.length) {
|
|
qb.andWhere('tipoUso.id_uso IN (:...usos)', {
|
|
usos: filtros.usos
|
|
})
|
|
}
|
|
|
|
if (filtros?.antiguedad?.length && !filtros.antiguedad.includes("Todos")) {
|
|
qb.andWhere('equipo.antiguedad IN (:...antiguedad)', {
|
|
antiguedad: filtros.antiguedad
|
|
})
|
|
}
|
|
|
|
// selector dinámico
|
|
|
|
switch (tipo) {
|
|
|
|
case 'antiguedad':
|
|
|
|
qb.select('equipo.antiguedad', 'antiguedad')
|
|
.addSelect('COUNT(*)', 'total')
|
|
|
|
if (filtros?.adscripciones?.length) {
|
|
|
|
qb.addSelect('adscripcion.adscripcion', 'adscripcion')
|
|
|
|
qb.groupBy('equipo.antiguedad')
|
|
.addGroupBy('adscripcion.adscripcion')
|
|
|
|
} else {
|
|
|
|
qb.groupBy('equipo.antiguedad')
|
|
|
|
}
|
|
|
|
qb.orderBy(`
|
|
CASE
|
|
WHEN equipo.antiguedad = 'Menor a 2 años' THEN 1
|
|
WHEN equipo.antiguedad = 'Entre 2 y 3 años' THEN 2
|
|
WHEN equipo.antiguedad = 'Entre 4 y 5 años' THEN 3
|
|
WHEN equipo.antiguedad = 'Mayor a 6 años' THEN 4
|
|
END
|
|
`)
|
|
|
|
break
|
|
|
|
case 'uso':
|
|
|
|
qb.select('tipoUso.tipo_uso', 'uso')
|
|
.addSelect('COUNT(*)', 'total')
|
|
|
|
if (filtros?.adscripciones?.length) {
|
|
|
|
qb.addSelect('adscripcion.adscripcion', 'adscripcion')
|
|
|
|
qb.groupBy('tipoUso.tipo_uso')
|
|
.addGroupBy('adscripcion.adscripcion')
|
|
|
|
} else {
|
|
|
|
qb.groupBy('tipoUso.tipo_uso')
|
|
|
|
}
|
|
|
|
qb.orderBy(`
|
|
CASE
|
|
WHEN tipoUso.tipo_uso = 'ALUMNO' THEN 1
|
|
WHEN tipoUso.tipo_uso = 'PROFESOR' THEN 2
|
|
WHEN tipoUso.tipo_uso = 'ADMINISTRATIVO' THEN 3
|
|
WHEN tipoUso.tipo_uso = 'TÉCNICO ACADEMICO' THEN 4
|
|
END`)
|
|
|
|
break
|
|
|
|
case 'so':
|
|
|
|
qb.select('sistemaOperativo.sistema_operativo', 'so')
|
|
.addSelect('COUNT(*)', 'total')
|
|
|
|
if (filtros?.adscripciones?.length) {
|
|
|
|
qb.addSelect('adscripcion.adscripcion', 'adscripcion')
|
|
|
|
qb.groupBy('sistemaOperativo.sistema_operativo')
|
|
.addGroupBy('adscripcion.adscripcion')
|
|
|
|
} else {
|
|
|
|
qb.groupBy('sistemaOperativo.sistema_operativo')
|
|
|
|
}
|
|
qb.orderBy(`equipo.adscripcion`, "ASC")
|
|
|
|
break
|
|
|
|
case 'procesador':
|
|
|
|
qb.select('procesador.procesador', 'procesador')
|
|
.addSelect('COUNT(*)', 'total')
|
|
|
|
if (filtros?.adscripciones?.length) {
|
|
|
|
qb.addSelect('adscripcion.adscripcion', 'adscripcion')
|
|
|
|
qb.groupBy('procesador.procesador')
|
|
.addGroupBy('adscripcion.adscripcion')
|
|
|
|
} else {
|
|
|
|
qb.groupBy('procesador.procesador')
|
|
|
|
}
|
|
qb.orderBy(`equipo.adscripcion`, "ASC")
|
|
|
|
break
|
|
|
|
}
|
|
return qb.getRawMany()
|
|
|
|
}
|
|
|
|
|
|
async tabla(filtros?: FiltrosTablaDto) {
|
|
const qb = this.equipoRepository
|
|
.createQueryBuilder('equipo')
|
|
.select([])
|
|
|
|
qb.leftJoin('equipo.adscripcion', 'adscripcion')
|
|
qb.leftJoin('equipo.procesador', 'procesador')
|
|
qb.leftJoin('equipo.sistemaOperativo', 'sistemaOperativo')
|
|
qb.leftJoin('equipo.tipoUso', 'tipoUso')
|
|
|
|
qb.addSelect('equipo.inventario', 'inventario')
|
|
qb.addSelect('adscripcion.adscripcion', 'adscripcion')
|
|
qb.addSelect('equipo.lugar', 'ubicacion')
|
|
|
|
const tieneFiltroReal = (arr?: string[]) => arr?.length && !arr.includes("0") && !arr.includes("Todos")
|
|
qb.andWhere('equipo.id_periferico IS NULL')
|
|
|
|
// ADSCRIPCIONES
|
|
if (filtros?.adscripciones?.length) {
|
|
|
|
// siempre selecciona
|
|
qb.addSelect('adscripcion.adscripcion', 'adscripcion')
|
|
|
|
if (tieneFiltroReal(filtros.adscripciones)) {
|
|
qb.andWhere('adscripcion.id_adscripcion IN (:...adscripciones)', {
|
|
adscripciones: filtros.adscripciones
|
|
})
|
|
}
|
|
}
|
|
|
|
// PROCESADOR
|
|
if (filtros?.procesadores?.length) {
|
|
|
|
qb.addSelect('procesador.procesador', 'procesador')
|
|
|
|
if (tieneFiltroReal(filtros.procesadores)) {
|
|
qb.andWhere('procesador.id_procesador IN (:...procesadores)', {
|
|
procesadores: filtros.procesadores
|
|
})
|
|
}
|
|
}
|
|
|
|
// SISTEMA OPERATIVO
|
|
if (filtros?.sistemas?.length) {
|
|
|
|
qb.addSelect('sistemaOperativo.sistema_operativo', 'so')
|
|
|
|
if (tieneFiltroReal(filtros.sistemas)) {
|
|
qb.andWhere('sistemaOperativo.id_sistema_operativo IN (:...sistemas)', {
|
|
sistemas: filtros.sistemas
|
|
})
|
|
}
|
|
}
|
|
|
|
// USO
|
|
if (filtros?.usos?.length) {
|
|
|
|
qb.addSelect('tipoUso.tipo_uso', 'uso')
|
|
|
|
if (tieneFiltroReal(filtros.usos)) {
|
|
qb.andWhere('tipoUso.id_uso IN (:...usos)', {
|
|
usos: filtros.usos
|
|
})
|
|
}
|
|
}
|
|
|
|
// ANTIGÜEDAD
|
|
if (filtros?.antiguedad?.length) {
|
|
|
|
qb.addSelect('equipo.antiguedad', 'antiguedad')
|
|
|
|
if (tieneFiltroReal(filtros.antiguedad)) {
|
|
qb.andWhere('equipo.antiguedad IN (:...antiguedad)', {
|
|
antiguedad: filtros.antiguedad
|
|
})
|
|
}
|
|
}
|
|
|
|
return qb
|
|
.orderBy(`equipo.adscripcion`, "DESC")
|
|
.getRawMany()
|
|
}
|
|
|
|
async tablaCount(filtros?: FiltrosTablaDto) {
|
|
const qb = this.equipoRepository
|
|
.createQueryBuilder('equipo')
|
|
.select([])
|
|
|
|
qb.leftJoin('equipo.adscripcion', 'adscripcion')
|
|
qb.leftJoin('equipo.procesador', 'procesador')
|
|
qb.leftJoin('equipo.sistemaOperativo', 'sistemaOperativo')
|
|
qb.leftJoin('equipo.tipoUso', 'tipoUso')
|
|
|
|
qb.addSelect('adscripcion.adscripcion', 'adscripcion')
|
|
qb.andWhere('equipo.id_periferico IS NULL')
|
|
if (filtros?.adscripciones?.length) {
|
|
qb.andWhere('adscripcion.id_adscripcion IN (:...adscripciones)', {
|
|
adscripciones: filtros.adscripciones
|
|
})
|
|
}
|
|
|
|
if (filtros?.procesadores?.length) {
|
|
qb.andWhere('procesador.id_procesador IN (:...procesadores)', {
|
|
procesadores: filtros.procesadores
|
|
})
|
|
}
|
|
|
|
if (filtros?.sistemas?.length) {
|
|
qb.andWhere('sistemaOperativo.id_sistema_operativo IN (:...sistemas)', {
|
|
sistemas: filtros.sistemas
|
|
})
|
|
}
|
|
|
|
if (filtros?.usos?.length) {
|
|
qb.andWhere('tipoUso.id_uso IN (:...usos)', {
|
|
usos: filtros.usos
|
|
})
|
|
}
|
|
|
|
if (filtros?.antiguedad?.length && !filtros.antiguedad.includes("Todos")) {
|
|
qb.andWhere('equipo.antiguedad IN (:...antiguedad)', {
|
|
antiguedad: filtros.antiguedad
|
|
})
|
|
}
|
|
|
|
return qb
|
|
.addSelect('COUNT(*)', 'total')
|
|
.addGroupBy('adscripcion.adscripcion')
|
|
.orderBy(`equipo.adscripcion`, "DESC")
|
|
.getRawMany()
|
|
}
|
|
|
|
async tablaExcel(filtros?: FiltrosTablaDto) {
|
|
const qb = this.equipoRepository
|
|
.createQueryBuilder('equipo')
|
|
.select([]);
|
|
|
|
qb.leftJoin('equipo.adscripcion', 'adscripcion');
|
|
qb.leftJoin('equipo.procesador', 'procesador');
|
|
qb.leftJoin('equipo.sistemaOperativo', 'sistemaOperativo');
|
|
qb.leftJoin('equipo.tipoUso', 'tipoUso');
|
|
|
|
qb.addSelect('equipo.inventario', 'inventario');
|
|
qb.addSelect('adscripcion.adscripcion', 'adscripcion');
|
|
qb.addSelect('equipo.lugar', 'ubicacion');
|
|
|
|
const tieneFiltroReal = (arr?: string[]) => arr?.length && !arr.includes("0") && !arr.includes("Todos");
|
|
|
|
qb.andWhere('equipo.id_periferico IS NULL')
|
|
// ADSCRIPCIONES
|
|
if (filtros?.adscripciones?.length) {
|
|
|
|
qb.addSelect('adscripcion.adscripcion', 'adscripcion');
|
|
|
|
if (tieneFiltroReal(filtros.adscripciones)) {
|
|
qb.andWhere('adscripcion.id_adscripcion IN (:...adscripciones)', {
|
|
adscripciones: filtros.adscripciones
|
|
});
|
|
}
|
|
}
|
|
|
|
// PROCESADOR
|
|
if (filtros?.procesadores?.length) {
|
|
|
|
qb.addSelect('procesador.procesador', 'procesador');
|
|
|
|
if (tieneFiltroReal(filtros.procesadores)) {
|
|
qb.andWhere('procesador.id_procesador IN (:...procesadores)', {
|
|
procesadores: filtros.procesadores
|
|
});
|
|
}
|
|
}
|
|
|
|
// SISTEMA OPERATIVO
|
|
if (filtros?.sistemas?.length) {
|
|
|
|
qb.addSelect('sistemaOperativo.sistema_operativo', 'so');
|
|
|
|
if (tieneFiltroReal(filtros.sistemas)) {
|
|
qb.andWhere('sistemaOperativo.id_sistema_operativo IN (:...sistemas)', {
|
|
sistemas: filtros.sistemas
|
|
});
|
|
}
|
|
}
|
|
|
|
// USO
|
|
if (filtros?.usos?.length) {
|
|
|
|
qb.addSelect('tipoUso.tipo_uso', 'uso');
|
|
|
|
if (tieneFiltroReal(filtros.usos)) {
|
|
qb.andWhere('tipoUso.id_uso IN (:...usos)', {
|
|
usos: filtros.usos
|
|
});
|
|
}
|
|
}
|
|
|
|
// ANTIGÜEDAD
|
|
if (filtros?.antiguedad?.length) {
|
|
|
|
qb.addSelect('equipo.antiguedad', 'antiguedad');
|
|
|
|
if (tieneFiltroReal(filtros.antiguedad)) {
|
|
qb.andWhere('equipo.antiguedad IN (:...antiguedad)', {
|
|
antiguedad: filtros.antiguedad
|
|
});
|
|
}
|
|
}
|
|
|
|
const data = await qb
|
|
.orderBy(`equipo.adscripcion`, "DESC")
|
|
.getRawMany();
|
|
|
|
const workbook = new ExcelJS.Workbook();
|
|
const sheet = workbook.addWorksheet('Equipos');
|
|
|
|
const columns = [
|
|
{ header: 'Inventario', key: 'inventario', width: 20 },
|
|
{ header: 'Ubicación', key: 'ubicacion', width: 40 },
|
|
{ header: 'Adscripción', key: 'adscripcion', width: 40 },
|
|
];
|
|
|
|
if (data[0]?.procesador !== undefined) {
|
|
columns.push({ header: 'Procesador', key: 'procesador', width: 25 });
|
|
}
|
|
|
|
if (data[0]?.so !== undefined) {
|
|
columns.push({ header: 'Sistema Operativo', key: 'so', width: 25 });
|
|
}
|
|
|
|
if (data[0]?.uso !== undefined) {
|
|
columns.push({ header: 'Uso', key: 'uso', width: 20 });
|
|
}
|
|
|
|
if (data[0]?.antiguedad !== undefined) {
|
|
columns.push({ header: 'Antigüedad', key: 'antiguedad', width: 15 });
|
|
}
|
|
|
|
sheet.columns = columns;
|
|
|
|
data.forEach(row => {
|
|
sheet.addRow(row);
|
|
});
|
|
|
|
sheet.getRow(1).font = { bold: true };
|
|
|
|
return await workbook.xlsx.writeBuffer();
|
|
}
|
|
|
|
async tablaCountExcel(filtros?: FiltrosGraficaDto) {
|
|
const qb = this.equipoRepository
|
|
.createQueryBuilder('equipo')
|
|
.select([]);
|
|
|
|
qb.leftJoin('equipo.adscripcion', 'adscripcion');
|
|
qb.leftJoin('equipo.procesador', 'procesador');
|
|
qb.leftJoin('equipo.sistemaOperativo', 'sistemaOperativo');
|
|
qb.leftJoin('equipo.tipoUso', 'tipoUso');
|
|
qb.addSelect('adscripcion.adscripcion', 'adscripcion');
|
|
|
|
qb.andWhere('equipo.id_periferico IS NULL')
|
|
if (filtros?.adscripciones?.length) {
|
|
qb.andWhere('adscripcion.id_adscripcion IN (:...adscripciones)', {
|
|
adscripciones: filtros.adscripciones
|
|
});
|
|
}
|
|
|
|
if (filtros?.procesadores?.length) {
|
|
qb.andWhere('procesador.id_procesador IN (:...procesadores)', {
|
|
procesadores: filtros.procesadores
|
|
});
|
|
}
|
|
|
|
if (filtros?.sistemas?.length) {
|
|
qb.andWhere('sistemaOperativo.id_sistema_operativo IN (:...sistemas)', {
|
|
sistemas: filtros.sistemas
|
|
});
|
|
}
|
|
|
|
if (filtros?.usos?.length) {
|
|
qb.andWhere('tipoUso.id_uso IN (:...usos)', {
|
|
usos: filtros.usos
|
|
});
|
|
}
|
|
|
|
if (filtros?.antiguedad?.length && !filtros.antiguedad.includes("Todos")) {
|
|
qb.andWhere('equipo.antiguedad IN (:...antiguedad)', {
|
|
antiguedad: filtros.antiguedad
|
|
});
|
|
}
|
|
|
|
const data = await qb
|
|
.addSelect('COUNT(*)', 'total')
|
|
.addGroupBy('adscripcion.adscripcion')
|
|
.orderBy(`equipo.adscripcion`, "DESC")
|
|
.getRawMany();
|
|
|
|
const workbook = new ExcelJS.Workbook();
|
|
const sheet = workbook.addWorksheet('Resumen');
|
|
|
|
sheet.columns = [
|
|
{ header: 'Adscripción', key: 'adscripcion', width: 30 },
|
|
{ header: 'Total', key: 'total', width: 15 },
|
|
];
|
|
|
|
data.forEach(row => {
|
|
sheet.addRow(row);
|
|
});
|
|
|
|
sheet.getRow(1).font = { bold: true };
|
|
|
|
return await workbook.xlsx.writeBuffer();
|
|
}
|
|
}
|
|
|
|
let estado_excluidos = ['DE BAJA'];
|
|
let estado_inclyuidos = ['EN DESUSO', 'EN USO'];
|
|
|
|
let escritorio = ['ESCRITORIO PC', 'ESCRITORIO MAC OS ', 'ESCRITORIO LINUX'];
|
|
let portatil = [
|
|
'PORTÁTILES WINDOWS',
|
|
'PORTÁTILES CHROMEBOOK',
|
|
'PORTÁTILES MAC OS',
|
|
];
|
|
|
|
let equipos_mac = ['ESCRITORIO MAC OS ', 'PORTÁTILES MAC OS'];
|
|
|
|
let equpos_pc = ['ESCRITORIO PC', 'ESCRITORIO LINUX'];
|
|
let estritorio_mac = 'ESCRITORIO MAC OS ';
|
|
let portatiles_mac = 'PORTÁTILES MAC OS';
|
|
|
|
let portatiles = ['PORTÁTILES WINDOWS', 'PORTÁTILES CHROMEBOOK'];
|
|
|
|
let tabletas = ['TABLETA ANDROID', 'TABLETA iPAD OS'];
|
|
|
|
let impresoras = [
|
|
'INYECCIÓN TINTA',
|
|
'LÁSER DE ALTO VOLUMEN B/N',
|
|
'LÁSER DE ALTO VOLUMEN COLOR',
|
|
'LÁSER PEQUEÑA B/N',
|
|
'LÁSER PEQUEÑA COLOR',
|
|
'MATRIZ DE PUNTOS',
|
|
'MULTIFUNCIONALES',
|
|
'IMPRESORA TÉRMICA',
|
|
'IMPRESORA CREDENCIALES',
|
|
'PLOTTER',
|
|
];
|
|
|
|
let dijitales = [
|
|
'3D',
|
|
'DIGITALIZADOR DE CAMA PLANA PARA OFICINA',
|
|
'DIGITALIZADOR DE GRAN VOLUMEN',
|
|
'DIGITALIZADOR CON ALIMENTADOR DE HOJAS PARA OFICINA',
|
|
];
|
|
|
|
let servidor = 'SERVIDOR';
|