Files
Censo_api/src/equipo/equipo.service.ts
T

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';