feat(cfdi): descarga masiva de XMLs como ZIP, limite 1,000
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import type { Request, Response, NextFunction } from 'express';
|
||||
import * as cfdiService from '../services/cfdi.service.js';
|
||||
import { AppError } from '../middlewares/error.middleware.js';
|
||||
import AdmZip from 'adm-zip';
|
||||
import { GRUPO_PF_EMPRESARIAL, GRUPO_PM_OTROS } from '../services/dashboard.service.js';
|
||||
import { getRegimenesIgnoradosClaves } from '../services/regimen.service.js';
|
||||
import { resolveContribuyenteContext } from '../utils/contribuyente-context.js';
|
||||
@@ -75,6 +76,45 @@ export async function getXml(req: Request, res: Response, next: NextFunction) {
|
||||
}
|
||||
}
|
||||
|
||||
export async function downloadXmlsZip(req: Request, res: Response, next: NextFunction) {
|
||||
try {
|
||||
if (!req.tenantPool) {
|
||||
return next(new AppError(400, 'Tenant no configurado'));
|
||||
}
|
||||
|
||||
const ids = req.body.ids as number[];
|
||||
if (!Array.isArray(ids) || ids.length === 0) {
|
||||
return next(new AppError(400, 'Se requiere un array de IDs'));
|
||||
}
|
||||
if (ids.length > 1000) {
|
||||
return next(new AppError(400, 'Máximo 1,000 CFDIs por descarga'));
|
||||
}
|
||||
|
||||
const cfdis = await cfdiService.getXmlsByIds(req.tenantPool, ids);
|
||||
const zip = new AdmZip();
|
||||
let added = 0;
|
||||
|
||||
for (const cfdi of cfdis) {
|
||||
if (cfdi.xml) {
|
||||
const filename = `${cfdi.uuid || cfdi.id}.xml`;
|
||||
zip.addFile(filename, Buffer.from(cfdi.xml, 'utf8'));
|
||||
added++;
|
||||
}
|
||||
}
|
||||
|
||||
if (added === 0) {
|
||||
return next(new AppError(404, 'No se encontraron XMLs para los CFDIs seleccionados'));
|
||||
}
|
||||
|
||||
const zipBuffer = zip.toBuffer();
|
||||
res.set('Content-Type', 'application/zip');
|
||||
res.set('Content-Disposition', `attachment; filename="cfdis-${Date.now()}.zip"`);
|
||||
res.send(zipBuffer);
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
}
|
||||
|
||||
export async function listConceptos(req: Request, res: Response, next: NextFunction) {
|
||||
try {
|
||||
if (!req.tenantPool) return next(new AppError(400, 'Tenant no configurado'));
|
||||
|
||||
Reference in New Issue
Block a user