import type { Pool } from 'pg'; import { prisma } from '../config/database.js'; export async function getAllRegimenes() { return prisma.regimen.findMany({ where: { activo: true }, orderBy: { clave: 'asc' }, }); } export async function getRegimenesIgnorados(tenantId: string) { const rows = await prisma.tenantRegimenIgnorado.findMany({ where: { tenantId }, include: { regimen: true }, orderBy: { regimen: { clave: 'asc' } }, }); return rows.map(r => r.regimen); } export async function getRegimenesIgnoradosClaves(tenantId: string): Promise { const rows = await prisma.tenantRegimenIgnorado.findMany({ where: { tenantId }, include: { regimen: { select: { clave: true } } }, }); return rows.map(r => r.regimen.clave); } export async function getRegimenesActivos(tenantId: string) { const rows = await prisma.tenantRegimenActivo.findMany({ where: { tenantId }, include: { regimen: true }, orderBy: { regimen: { clave: 'asc' } }, }); return rows.map(r => r.regimen); } export async function getRegimenesActivosClaves(tenantId: string): Promise { const rows = await prisma.tenantRegimenActivo.findMany({ where: { tenantId }, include: { regimen: { select: { clave: true } } }, }); return rows.map(r => r.regimen.clave); } /** * Resuelve las claves de regímenes activos para la alerta de discrepancia. * Si hay contribuyenteId, lee de contribuyentes.regimen_fiscal (comma-separated). * Si no, combina TenantRegimenActivo (tabla central) con los regímenes de * todos los contribuyentes activos del tenant. Esto evita que la alerta * aparezca en el correo por-contribuyente pero desaparezca en el dashboard * cuando no hay un contribuyente seleccionado. */ export async function getRegimenesActivosClavesEfectivos( tenantId: string, pool: Pool, contribuyenteId?: string | null, ): Promise { if (contribuyenteId) { const safeId = contribuyenteId.replace(/[^a-f0-9-]/gi, ''); const { rows } = await pool.query( `SELECT regimen_fiscal FROM contribuyentes WHERE entidad_id = $1`, [safeId], ); if (rows.length > 0 && rows[0].regimen_fiscal) { return rows[0].regimen_fiscal.split(',').map((c: string) => c.trim()).filter(Boolean); } // Fallback: si el contribuyente no tiene regimen_fiscal, usamos los del tenant // para no perder la alerta si el campo quedó vacío accidentalmente. const tenantRegimenes = await getRegimenesActivosClaves(tenantId); if (tenantRegimenes.length > 0) return tenantRegimenes; const { rows: allRows } = await pool.query( `SELECT DISTINCT regimen_fiscal FROM contribuyentes WHERE regimen_fiscal IS NOT NULL AND regimen_fiscal <> ''`, ); const set = new Set(); for (const row of allRows) { if (row.regimen_fiscal) { for (const clave of row.regimen_fiscal.split(',')) { const trimmed = clave.trim(); if (trimmed) set.add(trimmed); } } } return Array.from(set); } const tenantRegimenes = await getRegimenesActivosClaves(tenantId); // Fallback: si no hay regímenes configurados a nivel tenant, usamos los // regímenes de todos los contribuyentes activos del tenant. if (tenantRegimenes.length > 0) { return tenantRegimenes; } const { rows } = await pool.query( `SELECT DISTINCT regimen_fiscal FROM contribuyentes WHERE regimen_fiscal IS NOT NULL AND regimen_fiscal <> ''`, ); const set = new Set(); for (const row of rows) { if (row.regimen_fiscal) { for (const clave of row.regimen_fiscal.split(',')) { const trimmed = clave.trim(); if (trimmed) set.add(trimmed); } } } return Array.from(set); } export async function setRegimenesActivos(tenantId: string, regimenIds: number[]) { await prisma.tenantRegimenActivo.deleteMany({ where: { tenantId } }); if (regimenIds.length > 0) { await prisma.tenantRegimenActivo.createMany({ data: regimenIds.map(regimenId => ({ tenantId, regimenId })), }); } return getRegimenesActivos(tenantId); } export async function setRegimenesIgnorados(tenantId: string, regimenIds: number[]) { // Delete all existing and re-insert await prisma.tenantRegimenIgnorado.deleteMany({ where: { tenantId } }); if (regimenIds.length > 0) { await prisma.tenantRegimenIgnorado.createMany({ data: regimenIds.map(regimenId => ({ tenantId, regimenId })), }); } return getRegimenesIgnorados(tenantId); }