fix(impuestos): desactivar JIT en queries con subplans correlacionados
- Agrega helper withJitOff en impuestos.service.ts - Ejecuta getResumenIva, getIvaMensual y readResumenIvaFromCache con SET LOCAL jit = off - Evita compilación JIT de ~17s en queries con costo estimado alto feat(contribuyentes): auto-asignar a cartera del supervisor - Al crear contribuyente con supervisorUserId, se agrega automáticamente a todas las carteras top-level del supervisor feat(permisos): restricciones de UI por rol en contribuyentes - Oculta botón Add-ons para roles distintos de owner/cfo - Oculta botón Eliminar contribuyente para no-owner - Oculta botón Agregar RFC para auxiliar/visor/cliente/contador feat(cfdi): ver CFDI desde conceptos y forma de pago en Excel - Agrega botón Ver CFDI en cada fila de la tabla de Conceptos - Agrega columna Forma de Pago en export Excel de CFDIs - Agrega columna Forma de Pago en export individual de CFDI chore(migraciones): índices GIN para relaciones de activos - 048: índices btree parciales para activos - 049: índices GIN para cfdis_relacionados y uuid_relacionado
This commit is contained in:
@@ -24,44 +24,62 @@
|
||||
* el de activos aplica también pero algunos predicados son no-op funcional
|
||||
* en subqueries que filtran por tipo_comprobante específico (Postgres los
|
||||
* optimiza away).
|
||||
*
|
||||
* OPTIMIZACIÓN: los subqueries de exclusiones de activos se reescribieron
|
||||
* para usar subqueries NO-correlacionados donde sea posible (casos 1-3).
|
||||
* Esto permite a PostgreSQL ejecutar el subquery una sola vez por query
|
||||
* principal, en lugar de una vez por cada fila. Solo el caso 4 (anticipo
|
||||
* referenciado por I07) requiere un correlated EXISTS.
|
||||
*/
|
||||
|
||||
const ACTIVOS_USOS = "('I01','I02','I03','I04','I05','I06','I07','I08')";
|
||||
|
||||
/**
|
||||
* Subquery no-correlacionado que devuelve todos los UUIDs de facturas tipo I
|
||||
* con uso de activo. Usado para lookups P→I y E→I.
|
||||
*/
|
||||
const UUIDS_ACTIVOS = `SELECT LOWER(uuid) AS uuid FROM cfdis WHERE tipo_comprobante = 'I' AND uso_cfdi IN ${ACTIVOS_USOS}`;
|
||||
|
||||
/**
|
||||
* Subquery no-correlacionado que devuelve todos los UUIDs de E's que
|
||||
* referencian un activo (directamente I-activo, o indirectamente P→I-activo).
|
||||
*
|
||||
* Usa JOIN + UNION en lugar de EXISTS + OR para que PostgreSQL pueda usar
|
||||
* índices de forma más efectiva (especialmente el GIN en cfdis_relacionados).
|
||||
*/
|
||||
const UUIDS_E_DE_ACTIVOS = `
|
||||
SELECT e.uuid
|
||||
FROM cfdis e
|
||||
JOIN cfdis r_act ON LOWER(r_act.uuid) = ANY(string_to_array(LOWER(e.cfdis_relacionados), '|'))
|
||||
WHERE e.tipo_comprobante = 'E'
|
||||
AND e.cfdis_relacionados IS NOT NULL
|
||||
AND r_act.tipo_comprobante = 'I'
|
||||
AND r_act.uso_cfdi IN ${ACTIVOS_USOS}
|
||||
UNION ALL
|
||||
SELECT e.uuid
|
||||
FROM cfdis e
|
||||
JOIN cfdis r_act ON LOWER(r_act.uuid) = ANY(string_to_array(LOWER(e.cfdis_relacionados), '|'))
|
||||
JOIN cfdis pi_act ON LOWER(pi_act.uuid) = LOWER(r_act.uuid_relacionado)
|
||||
WHERE e.tipo_comprobante = 'E'
|
||||
AND e.cfdis_relacionados IS NOT NULL
|
||||
AND r_act.tipo_comprobante = 'P'
|
||||
AND pi_act.tipo_comprobante = 'I'
|
||||
AND pi_act.uso_cfdi IN ${ACTIVOS_USOS}
|
||||
`;
|
||||
|
||||
/**
|
||||
* Predicado SQL que detecta si el row actual (sin alias de tabla, asume
|
||||
* `FROM cfdis`) referencia un activo directamente (I), indirectamente vía
|
||||
* pago (P→I), o transitivamente vía relación (E→I, E→P→I).
|
||||
*
|
||||
* IMPORTANTE — qualifying outer refs: dentro de los subqueries `cfdis i_act`
|
||||
* y `cfdis r_act`, la tabla interna también tiene columnas `uuid_relacionado`
|
||||
* y `cfdis_relacionados`. Una referencia no-qualificada las resolvería a las
|
||||
* columnas internas (NO al row outer), volviendo el predicado a no-op.
|
||||
* Por eso usamos `cfdis.uuid_relacionado` y `cfdis.cfdis_relacionados`
|
||||
* explícitamente — fuerza la resolución al outer.
|
||||
*/
|
||||
function activosExclusionNoAlias(): string {
|
||||
return `
|
||||
AND NOT (tipo_comprobante = 'I' AND uso_cfdi IN ${ACTIVOS_USOS})
|
||||
AND NOT (tipo_comprobante = 'P' AND EXISTS (
|
||||
SELECT 1 FROM cfdis i_act
|
||||
WHERE LOWER(i_act.uuid) = LOWER(cfdis.uuid_relacionado)
|
||||
AND i_act.tipo_comprobante = 'I'
|
||||
AND i_act.uso_cfdi IN ${ACTIVOS_USOS}
|
||||
))
|
||||
AND NOT (tipo_comprobante = 'E' AND cfdis.cfdis_relacionados IS NOT NULL AND EXISTS (
|
||||
SELECT 1 FROM cfdis r_act
|
||||
WHERE LOWER(r_act.uuid) = ANY(string_to_array(LOWER(cfdis.cfdis_relacionados), '|'))
|
||||
AND (
|
||||
(r_act.tipo_comprobante = 'I' AND r_act.uso_cfdi IN ${ACTIVOS_USOS})
|
||||
OR (r_act.tipo_comprobante = 'P' AND EXISTS (
|
||||
SELECT 1 FROM cfdis pi_act
|
||||
WHERE LOWER(pi_act.uuid) = LOWER(r_act.uuid_relacionado)
|
||||
AND pi_act.tipo_comprobante = 'I'
|
||||
AND pi_act.uso_cfdi IN ${ACTIVOS_USOS}
|
||||
))
|
||||
)
|
||||
SELECT 1 FROM (${UUIDS_ACTIVOS}) ua
|
||||
WHERE ua.uuid = ANY(string_to_array(LOWER(uuid_relacionado), '|'))
|
||||
))
|
||||
AND NOT (tipo_comprobante = 'E' AND uuid IN (${UUIDS_E_DE_ACTIVOS}))
|
||||
AND NOT (tipo_comprobante = 'I' AND EXISTS (
|
||||
-- Anticipo: CFDI tipo I (puede no tener uso_cfdi de activo) que es
|
||||
-- referenciado por una I/07 PPD con uso_cfdi de activo. La I/07 PPD
|
||||
@@ -87,24 +105,10 @@ function activosExclusionAlias(alias: string): string {
|
||||
return `
|
||||
AND NOT (${alias}.tipo_comprobante = 'I' AND ${alias}.uso_cfdi IN ${ACTIVOS_USOS})
|
||||
AND NOT (${alias}.tipo_comprobante = 'P' AND EXISTS (
|
||||
SELECT 1 FROM cfdis i_act
|
||||
WHERE LOWER(i_act.uuid) = LOWER(${alias}.uuid_relacionado)
|
||||
AND i_act.tipo_comprobante = 'I'
|
||||
AND i_act.uso_cfdi IN ${ACTIVOS_USOS}
|
||||
))
|
||||
AND NOT (${alias}.tipo_comprobante = 'E' AND ${alias}.cfdis_relacionados IS NOT NULL AND EXISTS (
|
||||
SELECT 1 FROM cfdis r_act
|
||||
WHERE LOWER(r_act.uuid) = ANY(string_to_array(LOWER(${alias}.cfdis_relacionados), '|'))
|
||||
AND (
|
||||
(r_act.tipo_comprobante = 'I' AND r_act.uso_cfdi IN ${ACTIVOS_USOS})
|
||||
OR (r_act.tipo_comprobante = 'P' AND EXISTS (
|
||||
SELECT 1 FROM cfdis pi_act
|
||||
WHERE LOWER(pi_act.uuid) = LOWER(r_act.uuid_relacionado)
|
||||
AND pi_act.tipo_comprobante = 'I'
|
||||
AND pi_act.uso_cfdi IN ${ACTIVOS_USOS}
|
||||
))
|
||||
)
|
||||
SELECT 1 FROM (${UUIDS_ACTIVOS}) ua
|
||||
WHERE ua.uuid = ANY(string_to_array(LOWER(${alias}.uuid_relacionado), '|'))
|
||||
))
|
||||
AND NOT (${alias}.tipo_comprobante = 'E' AND ${alias}.uuid IN (${UUIDS_E_DE_ACTIVOS}))
|
||||
AND NOT (${alias}.tipo_comprobante = 'I' AND EXISTS (
|
||||
SELECT 1 FROM cfdis i07_act
|
||||
WHERE i07_act.tipo_comprobante = 'I'
|
||||
|
||||
Reference in New Issue
Block a user