Files
HoruxDespachosNuevo/apps/api/src/services/regimen.service.ts

136 lines
4.4 KiB
TypeScript

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<string[]> {
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<string[]> {
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<string[]> {
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<string>();
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<string>();
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);
}