import { prisma } from '../config/database.js'; import type { IvaMensual, IsrMensual, ResumenIva, ResumenIsr } from '@horux/shared'; export async function getIvaMensual(schema: string, año: number): Promise { const data = await prisma.$queryRawUnsafe(` SELECT id, año, mes, iva_trasladado as "ivaTrasladado", iva_acreditable as "ivaAcreditable", COALESCE(iva_retenido, 0) as "ivaRetenido", resultado, acumulado, estado, fecha_declaracion as "fechaDeclaracion" FROM "${schema}".iva_mensual WHERE año = $1 ORDER BY mes `, año); return data.map(row => ({ ...row, ivaTrasladado: Number(row.ivaTrasladado), ivaAcreditable: Number(row.ivaAcreditable), ivaRetenido: Number(row.ivaRetenido), resultado: Number(row.resultado), acumulado: Number(row.acumulado), })); } export async function getResumenIva(schema: string, año: number, mes: number): Promise { // Get from iva_mensual if exists const existing = await prisma.$queryRawUnsafe(` SELECT * FROM "${schema}".iva_mensual WHERE año = $1 AND mes = $2 `, año, mes); if (existing && existing.length > 0) { const record = existing[0]; const [acumuladoResult] = await prisma.$queryRawUnsafe<[{ total: number }]>(` SELECT COALESCE(SUM(resultado), 0) as total FROM "${schema}".iva_mensual WHERE año = $1 AND mes <= $2 `, año, mes); return { trasladado: Number(record.iva_trasladado || 0), acreditable: Number(record.iva_acreditable || 0), retenido: Number(record.iva_retenido || 0), resultado: Number(record.resultado || 0), acumuladoAnual: Number(acumuladoResult?.total || 0), }; } // Calculate from CFDIs if no iva_mensual record const [calcResult] = await prisma.$queryRawUnsafe<[{ trasladado: number; acreditable: number; retenido: number; }]>(` SELECT COALESCE(SUM(CASE WHEN tipo = 'ingreso' THEN iva ELSE 0 END), 0) as trasladado, COALESCE(SUM(CASE WHEN tipo = 'egreso' THEN iva ELSE 0 END), 0) as acreditable, COALESCE(SUM(iva_retenido), 0) as retenido FROM "${schema}".cfdis WHERE estado = 'vigente' AND EXTRACT(YEAR FROM fecha_emision) = $1 AND EXTRACT(MONTH FROM fecha_emision) = $2 `, año, mes); const trasladado = Number(calcResult?.trasladado || 0); const acreditable = Number(calcResult?.acreditable || 0); const retenido = Number(calcResult?.retenido || 0); const resultado = trasladado - acreditable - retenido; return { trasladado, acreditable, retenido, resultado, acumuladoAnual: resultado, }; } export async function getIsrMensual(schema: string, año: number): Promise { // Check if isr_mensual table exists try { const data = await prisma.$queryRawUnsafe(` SELECT id, año, mes, ingresos_acumulados as "ingresosAcumulados", deducciones, base_gravable as "baseGravable", isr_causado as "isrCausado", isr_retenido as "isrRetenido", isr_a_pagar as "isrAPagar", estado, fecha_declaracion as "fechaDeclaracion" FROM "${schema}".isr_mensual WHERE año = $1 ORDER BY mes `, año); return data.map(row => ({ ...row, ingresosAcumulados: Number(row.ingresosAcumulados), deducciones: Number(row.deducciones), baseGravable: Number(row.baseGravable), isrCausado: Number(row.isrCausado), isrRetenido: Number(row.isrRetenido), isrAPagar: Number(row.isrAPagar), })); } catch { // Table doesn't exist, return empty array return []; } } export async function getResumenIsr(schema: string, año: number, mes: number): Promise { // Calculate from CFDIs const [ingresos] = await prisma.$queryRawUnsafe<[{ total: number }]>(` SELECT COALESCE(SUM(total), 0) as total FROM "${schema}".cfdis WHERE tipo = 'ingreso' AND estado = 'vigente' AND EXTRACT(YEAR FROM fecha_emision) = $1 AND EXTRACT(MONTH FROM fecha_emision) <= $2 `, año, mes); const [egresos] = await prisma.$queryRawUnsafe<[{ total: number }]>(` SELECT COALESCE(SUM(total), 0) as total FROM "${schema}".cfdis WHERE tipo = 'egreso' AND estado = 'vigente' AND EXTRACT(YEAR FROM fecha_emision) = $1 AND EXTRACT(MONTH FROM fecha_emision) <= $2 `, año, mes); const [retenido] = await prisma.$queryRawUnsafe<[{ total: number }]>(` SELECT COALESCE(SUM(isr_retenido), 0) as total FROM "${schema}".cfdis WHERE estado = 'vigente' AND EXTRACT(YEAR FROM fecha_emision) = $1 AND EXTRACT(MONTH FROM fecha_emision) <= $2 `, año, mes); const ingresosAcumulados = Number(ingresos?.total || 0); const deducciones = Number(egresos?.total || 0); const baseGravable = Math.max(0, ingresosAcumulados - deducciones); // Simplified ISR calculation (actual calculation would use SAT tables) const isrCausado = baseGravable * 0.30; // 30% simplified rate const isrRetenido = Number(retenido?.total || 0); const isrAPagar = Math.max(0, isrCausado - isrRetenido); return { ingresosAcumulados, deducciones, baseGravable, isrCausado, isrRetenido, isrAPagar, }; }