'use client'; import { useState, useEffect } from 'react'; import { useCfdisConConciliacion, useConciliar, useDesconciliar } from '@/lib/hooks/use-conciliacion'; import { useBancos } from '@/lib/hooks/use-bancos'; import { useRegimenesDelPeriodo } from '@/lib/hooks/use-dashboard'; import { PeriodSelector, RegimenSelector } from '@horux/shared-ui'; import { CfdiViewerModal } from '@/components/cfdi/cfdi-viewer-modal'; import { Header } from '@/components/layouts/header'; import { Card, CardContent, Button, Select, SelectContent, SelectItem, SelectTrigger, SelectValue, Input } from '@horux/shared-ui'; import { useAuthStore } from '@/stores/auth-store'; import { formatCurrency } from '@/lib/utils'; import { exportToExcel } from '@/lib/export-excel'; import { Eye, Download, X, CheckCircle } from 'lucide-react'; function getMonthRange(year: number, month: number) { const start = `${year}-${String(month).padStart(2, '0')}-01`; const lastDay = new Date(year, month, 0).getDate(); const end = `${year}-${String(month).padStart(2, '0')}-${String(lastDay).padStart(2, '0')}`; return { start, end }; } export default function ConciliacionPage() { const now = new Date(); const defaultRange = getMonthRange(now.getFullYear(), now.getMonth() + 1); const [fechaInicio, setFechaInicio] = useState(defaultRange.start); const [fechaFin, setFechaFin] = useState(defaultRange.end); const [regimenSeleccionado, setRegimenSeleccionado] = useState(null); const [activeTab, setActiveTab] = useState<'EMITIDO' | 'RECIBIDO'>('EMITIDO'); const [selected, setSelected] = useState>(new Set()); const [fechaPago, setFechaPago] = useState(''); const [bancoId, setBancoId] = useState(''); const [selectedCfdi, setSelectedCfdi] = useState(null); const { user } = useAuthStore(); const isVisor = user?.role === 'visor'; // Data const { data: regimenes, isLoading: regimenesLoading } = useRegimenesDelPeriodo(fechaInicio, fechaFin); const { data: cfdis, isLoading } = useCfdisConConciliacion({ tipo: activeTab, fechaInicio, fechaFin, ...(regimenSeleccionado && { regimen: regimenSeleccionado }), }); const { data: bancos } = useBancos(); const conciliarMut = useConciliar(); const desconciliarMut = useDesconciliar(); // Split data const pendientes = cfdis?.filter((c) => c.conciliado !== 'true') || []; const conciliadas = cfdis?.filter((c) => c.conciliado === 'true') || []; // Score cards — tipo P usa monto_pago_mxn, otros usan total_mxn const getMonto = (c: any) => Number(c.montoMxn || c.totalMxn || 0); const montoConciliado = conciliadas.reduce((s, c) => s + getMonto(c), 0); const montoPendiente = pendientes.reduce((s, c) => s + getMonto(c), 0); // Reset selection on tab/filter change useEffect(() => { setSelected(new Set()); }, [activeTab, fechaInicio, fechaFin, regimenSeleccionado]); // Handlers const toggleSelect = (id: number) => { setSelected((prev) => { const next = new Set(prev); if (next.has(id)) { next.delete(id); } else { next.add(id); } return next; }); }; const toggleSelectAll = () => { if (selected.size === pendientes.length && pendientes.length > 0) { setSelected(new Set()); } else { setSelected(new Set(pendientes.map((c) => c.id))); } }; const handleConciliar = async () => { if (selected.size === 0 || !fechaPago || !bancoId) return; try { await conciliarMut.mutateAsync({ cfdiIds: Array.from(selected), fechaDePago: fechaPago, idBanco: parseInt(bancoId), }); setSelected(new Set()); setFechaPago(''); setBancoId(''); } catch (err: any) { alert(err.response?.data?.message || 'Error al conciliar'); } }; const handleDesconciliar = async (conciliacionId: number) => { if (!confirm('¿Desconciliar este CFDI?')) return; try { await desconciliarMut.mutateAsync(conciliacionId); } catch (err: any) { alert(err.response?.data?.message || 'Error al desconciliar'); } }; const handleExport = () => { if (!cfdis?.length) return; exportToExcel( cfdis.map((c) => ({ ...c, _fecha: new Date(c.fechaEmision).toLocaleDateString('es-MX'), _totalMxn: getMonto(c), _estado: c.conciliado === 'true' ? 'Conciliado' : 'Pendiente', _fechaPago: c.conciliacion?.fechaDePago || '', _banco: c.conciliacion ? `${c.conciliacion.banco} ****${c.conciliacion.terminacionCuenta}` : '', })), [ { header: 'UUID', key: 'uuid', width: 40 }, { header: 'Fecha Emisión', key: '_fecha', width: 15 }, { header: 'RFC Emisor', key: 'rfcEmisor', width: 15 }, { header: 'Nombre Emisor', key: 'nombreEmisor', width: 30 }, { header: 'RFC Receptor', key: 'rfcReceptor', width: 15 }, { header: 'Total MXN', key: '_totalMxn', width: 15 }, { header: 'Estado', key: '_estado', width: 12 }, { header: 'Fecha Pago', key: '_fechaPago', width: 15 }, { header: 'Banco', key: '_banco', width: 20 }, ], `conciliacion-${activeTab.toLowerCase()}`, ); }; return ( <>
{ setFechaInicio(i); setFechaFin(f); }} />
{/* Regimen selector + Export button */}
{/* Score cards */}

Monto Conciliado

{formatCurrency(montoConciliado)}

{conciliadas.length} CFDIs

Monto Pendiente de Conciliar

{formatCurrency(montoPendiente)}

{pendientes.length} CFDIs

{/* Tabs */}
{(['EMITIDO', 'RECIBIDO'] as const).map((tab) => ( ))}
{isLoading ? (
Cargando...
) : ( <> {/* Por conciliar */}

Por conciliar ({pendientes.length})

{pendientes.length === 0 ? (

No hay CFDIs pendientes de conciliar

) : (
{!isVisor && ( )} {pendientes.map((cfdi) => ( {!isVisor && ( )} ))}
0 } onChange={toggleSelectAll} /> UUID Fecha RFC Emisor Nombre Emisor RFC Receptor Nombre Receptor Total MXN M. Pago
toggleSelect(cfdi.id)} /> {cfdi.uuid?.substring(0, 8)} {new Date(cfdi.fechaEmision).toLocaleDateString('es-MX')} {cfdi.rfcEmisor} {cfdi.nombreEmisor} {cfdi.rfcReceptor} {cfdi.nombreReceptor} {formatCurrency(getMonto(cfdi))} {cfdi.metodoPago || '-'}
)}
{/* Action bar - only when items selected */} {!isVisor && selected.size > 0 && (
{selected.size} seleccionados setFechaPago(e.target.value)} className="w-44" />
)} {/* Conciliadas */}

Conciliadas ({conciliadas.length})

{conciliadas.length === 0 ? (

No hay CFDIs conciliados

) : (
{conciliadas.map((cfdi) => ( ))}
UUID Fecha Emisión RFC Emisor Nombre Emisor Total MXN Fecha Pago Banco
{cfdi.uuid?.substring(0, 8)} {new Date(cfdi.fechaEmision).toLocaleDateString('es-MX')} {cfdi.rfcEmisor} {cfdi.nombreEmisor} {formatCurrency(getMonto(cfdi))} {cfdi.conciliacion?.fechaDePago ? new Date( cfdi.conciliacion.fechaDePago + 'T12:00:00', ).toLocaleDateString('es-MX') : '-'} {cfdi.conciliacion ? `${cfdi.conciliacion.banco} ****${cfdi.conciliacion.terminacionCuenta}` : '-'} {!isVisor && cfdi.conciliacion && ( )}
)}
)}
setSelectedCfdi(null)} /> ); }