fix(facturacion): filtrar searchConceptos y searchRfcs por contribuyenteId

- searchConceptos: agrega AND c.contribuyente_id =  cuando se recibe contribuyenteId
- searchRfcs: restringe el catálogo global de rfcs a aquellos que aparecen en CFDIs del contribuyente (como emisor o receptor)
- Usa parametrización dinámica (3800099{params.length}) para evitar errores de índice
This commit is contained in:
Horux Dev
2026-05-28 21:44:32 +00:00
parent 2208cee87f
commit e01422e443

View File

@@ -580,7 +580,13 @@ export async function searchConceptos(req: Request, res: Response, next: NextFun
const params: any[] = [];
if (q.length >= 2) {
params.push(`%${q}%`);
whereSearch = `AND (cc.descripcion ILIKE $1 OR cc.clave_prod_serv ILIKE $1)`;
whereSearch = `AND (cc.descripcion ILIKE $${params.length} OR cc.clave_prod_serv ILIKE $${params.length})`;
}
let whereContribuyente = '';
if (contribuyenteId) {
params.push(contribuyenteId);
whereContribuyente = `AND c.contribuyente_id = $${params.length}`;
}
const { rows } = await pool.query(`
@@ -605,6 +611,7 @@ export async function searchConceptos(req: Request, res: Response, next: NextFun
WHERE c.status NOT IN ('Cancelado', '0')
${whereType}
${whereSearch}
${whereContribuyente}
ORDER BY cc.clave_prod_serv, cc.descripcion, c.fecha_emision DESC
LIMIT 30
`, params);
@@ -708,7 +715,7 @@ export async function searchRfcs(req: Request, res: Response, next: NextFunction
const q = (req.query.q as string || '').trim();
if (q.length < 3) return res.json([]);
const contribuyenteId = (req.query.contribuyenteId as string || '').trim();
const contribuyenteId = (req.query.contribuyenteId as string || '').replace(/[^a-f0-9-]/gi, '');
const pool = req.tenantPool!;
// RFC del tenant despacho para excluirlo (no se factura a sí mismo)
@@ -719,10 +726,17 @@ export async function searchRfcs(req: Request, res: Response, next: NextFunction
});
const tenantRfc = tenant?.rfc || '';
// Búsqueda en el catálogo completo de RFCs. El contribuyente activo solo
// filtra CFDIs relacionados / PPD, no el autocompleto de RFCs — de lo
// contrario no se podría facturar a un cliente nuevo que nunca haya
// aparecido en un CFDI previo.
const params: any[] = [tenantRfc, `%${q}%`];
let whereContribuyente = '';
if (contribuyenteId) {
params.push(contribuyenteId);
whereContribuyente = `AND id IN (
SELECT rfc_receptor_id FROM cfdis WHERE contribuyente_id = $${params.length} AND rfc_receptor_id IS NOT NULL
UNION
SELECT rfc_emisor_id FROM cfdis WHERE contribuyente_id = $${params.length} AND rfc_emisor_id IS NOT NULL
)`;
}
const { rows } = await pool.query(`
SELECT id, rfc, razon_social as "razonSocial",
regimen_fiscal as "regimenFiscal",
@@ -730,9 +744,10 @@ export async function searchRfcs(req: Request, res: Response, next: NextFunction
FROM rfcs
WHERE rfc != $1
AND (rfc ILIKE $2 OR razon_social ILIKE $2)
${whereContribuyente}
ORDER BY razon_social
LIMIT 10
`, [tenantRfc, `%${q}%`]);
`, params);
res.json(rows);
} catch (error) { next(error); }