Initial commit - Horux Despachos NL

This commit is contained in:
2026-05-03 16:47:53 -06:00
commit b00b677c54
647 changed files with 133843 additions and 0 deletions

View File

@@ -0,0 +1,125 @@
import ExcelJS from 'exceljs';
import type { Pool } from 'pg';
export async function exportCfdisToExcel(
pool: Pool,
filters: { tipo?: string; estado?: string; fechaInicio?: string; fechaFin?: string }
): Promise<Buffer> {
let whereClause = 'WHERE 1=1';
const params: any[] = [];
let paramIndex = 1;
if (filters.tipo) {
whereClause += ` AND type = $${paramIndex++}`;
params.push(filters.tipo);
}
if (filters.estado) {
whereClause += ` AND status = $${paramIndex++}`;
params.push(filters.estado);
}
if (filters.fechaInicio) {
whereClause += ` AND fecha_emision >= $${paramIndex++}`;
params.push(filters.fechaInicio);
}
if (filters.fechaFin) {
whereClause += ` AND fecha_emision <= $${paramIndex++}`;
params.push(filters.fechaFin);
}
const { rows: cfdis } = await pool.query(`
SELECT uuid, type, serie, folio, fecha_emision, status,
rfc_emisor, nombre_emisor, rfc_receptor, nombre_receptor,
subtotal, subtotal_mxn, descuento, descuento_mxn,
iva_traslado, iva_traslado_mxn, isr_retencion, isr_retencion_mxn,
iva_retencion, iva_retencion_mxn,
total, total_mxn, moneda, tipo_cambio,
metodo_pago, forma_pago, uso_cfdi
FROM cfdis
${whereClause}
ORDER BY fecha_emision DESC
`, params);
const workbook = new ExcelJS.Workbook();
const sheet = workbook.addWorksheet('CFDIs');
sheet.columns = [
{ header: 'UUID', key: 'uuid', width: 40 },
{ header: 'Tipo', key: 'type', width: 10 },
{ header: 'Serie', key: 'serie', width: 10 },
{ header: 'Folio', key: 'folio', width: 10 },
{ header: 'Fecha Emisión', key: 'fecha_emision', width: 15 },
{ header: 'RFC Emisor', key: 'rfc_emisor', width: 15 },
{ header: 'Nombre Emisor', key: 'nombre_emisor', width: 30 },
{ header: 'RFC Receptor', key: 'rfc_receptor', width: 15 },
{ header: 'Nombre Receptor', key: 'nombre_receptor', width: 30 },
{ header: 'Subtotal', key: 'subtotal', width: 15 },
{ header: 'Subtotal MXN', key: 'subtotal_mxn', width: 15 },
{ header: 'IVA Trasladado', key: 'iva_traslado', width: 15 },
{ header: 'IVA Trasladado MXN', key: 'iva_traslado_mxn', width: 15 },
{ header: 'Total', key: 'total', width: 15 },
{ header: 'Total MXN', key: 'total_mxn', width: 15 },
{ header: 'Moneda', key: 'moneda', width: 8 },
{ header: 'T.C.', key: 'tipo_cambio', width: 10 },
{ header: 'Estado', key: 'status', width: 12 },
];
sheet.getRow(1).font = { bold: true };
sheet.getRow(1).fill = {
type: 'pattern',
pattern: 'solid',
fgColor: { argb: 'FF4472C4' },
};
sheet.getRow(1).font = { bold: true, color: { argb: 'FFFFFFFF' } };
cfdis.forEach((cfdi: any) => {
sheet.addRow({
...cfdi,
fecha_emision: new Date(cfdi.fecha_emision).toLocaleDateString('es-MX'),
subtotal: Number(cfdi.subtotal),
subtotal_mxn: Number(cfdi.subtotal_mxn),
iva_traslado: Number(cfdi.iva_traslado),
iva_traslado_mxn: Number(cfdi.iva_traslado_mxn),
total: Number(cfdi.total),
total_mxn: Number(cfdi.total_mxn),
});
});
const buffer = await workbook.xlsx.writeBuffer();
return Buffer.from(buffer);
}
export async function exportReporteToExcel(
pool: Pool,
tipo: 'estado-resultados' | 'flujo-efectivo',
fechaInicio: string,
fechaFin: string
): Promise<Buffer> {
const workbook = new ExcelJS.Workbook();
const sheet = workbook.addWorksheet(tipo === 'estado-resultados' ? 'Estado de Resultados' : 'Flujo de Efectivo');
if (tipo === 'estado-resultados') {
const { rows: [totales] } = await pool.query(`
SELECT
COALESCE(SUM(CASE WHEN type = 'EMITIDO' AND tipo_comprobante = 'I' THEN subtotal_mxn ELSE 0 END), 0) as ingresos,
COALESCE(SUM(CASE WHEN type = 'RECIBIDO' AND tipo_comprobante = 'I' THEN subtotal_mxn ELSE 0 END), 0) as egresos
FROM cfdis
WHERE status NOT IN ('Cancelado', '0') AND fecha_emision BETWEEN $1 AND $2
`, [fechaInicio, fechaFin]);
sheet.columns = [
{ header: 'Concepto', key: 'concepto', width: 40 },
{ header: 'Monto', key: 'monto', width: 20 },
];
sheet.addRow({ concepto: 'INGRESOS', monto: '' });
sheet.addRow({ concepto: 'Total Ingresos', monto: Number(totales?.ingresos || 0) });
sheet.addRow({ concepto: '', monto: '' });
sheet.addRow({ concepto: 'EGRESOS', monto: '' });
sheet.addRow({ concepto: 'Total Egresos', monto: Number(totales?.egresos || 0) });
sheet.addRow({ concepto: '', monto: '' });
sheet.addRow({ concepto: 'UTILIDAD NETA', monto: Number(totales?.ingresos || 0) - Number(totales?.egresos || 0) });
}
const buffer = await workbook.xlsx.writeBuffer();
return Buffer.from(buffer);
}