| Cliente | Estado | |||||
|---|---|---|---|---|---|---|
|
{{ initials(c.full_name) }}
{{ c.full_name }} {{ c.document_number }} |
{{ c.status }} | |||||
| {{ clientes.loading ? 'Cargando...' : 'Sin clientes' }} | ||||||
| Cliente | Monto | Saldo | |||||
|---|---|---|---|---|---|---|---|
|
{{ initials(f.cliente_nombre) }}
{{ f.cliente_nombre || '—' }} {{ f.cliente_doc }} · {{ f.numero }} |
PYG {{ fmt(f.monto) }} | PYG {{ fmt(f.saldo) }} | |||||
| Sin facturas | |||||||
💰 Aplicar pago
{{ cobranzaCliente.cliente_nombre }}
{{ cobranzaCliente.facturas_pendientes }} facturas pendientes
Deuda total
PYG {{ fmt(cobranzaCliente.deuda_total) }}
{{ f.numero }}
Periodo {{ f.periodo }} · vence {{ f.vencimiento }}
Monto: PYG {{ fmt(f.monto) }}
Saldo: PYG {{ fmt(f.saldo) }}
Conectá tu red a Konexia
Cada concentrador Mikrotik se conecta vía túnel WireGuard a Konexia (no necesita IP pública).
Concentradores y routers de {{ tenant.name }}
{{ m.name }} {{ mtVpnLabel(m) }}
{{ m.host }}:{{ m.port }} · {{ m.role }} · {{ m.site || '—' }}
↻ handshake {{ peerHandshakeAge({last_handshake_at: m.vpn_last_handshake}) }} · ↓ {{ fmtBytes(m.vpn_rx_bytes) }} · ↑ {{ fmtBytes(m.vpn_tx_bytes) }} esperando primer handshake del Mikrotik
{{ m.detected_identity }} · v{{ m.detected_version }} · uptime {{ m.detected_uptime }}
Túneles WireGuard
{{ p.name }} {{ isPeerOnline(p) ? 'online' : 'sin handshake' }}
{{ p.assigned_ip }}
↻ {{ peerHandshakeAge(p) }}nunca conectó · ↓ {{ fmtBytes(p.rx_bytes) }} · ↑ {{ fmtBytes(p.tx_bytes) }}
↳ redes: {{ p.extra_networks }}
Conexiones para alcanzar OLTs/equipos en LAN del ISP
{{ c.name }} · {{ c.type }}
{{ c.wg_peer_ip }} · {{ c.wg_endpoint }}
Estado: {{ c.status }} · último handshake {{ c.wg_last_handshake }}
OLTs registradas en {{ tenant.name }}
{{ o.name }} · {{ o.vendor }} ⚠ sin concentrador @ {{ (mikrotiks.find(m=>m.id===o.mikrotik_id)||{}).name || ('MK#'+o.mikrotik_id) }}
{{ o.host }}:{{ o.port }} · {{ o.protocol }}
{{ o.model }} · {{ o.version_detected }}
{{ o.last_test_error }}
{{ onus.total }} ONUs autorizadas
| SN | Rx (dBm) | Tx (dBm) | Estado | |||
|---|---|---|---|---|---|---|
| {{ u.sn }} | {{ u.rx_dbm ?? '—' }} | {{ u.tx_dbm ?? '—' }} | {{ u.status }} | |||
| Sin ONUs | ||||||
Planes de internet de {{ tenant.name }}
{{ p.name }}
PYG {{ fmt(p.price) }}
Bajada
{{ p.download_mbps }} Mbps
Subida
{{ p.upload_mbps }} Mbps
Profile Mikrotik: {{ p.profile_name || '—' }}
{{ g.name }}
Provider: {{ g.provider }} · {{ g.mode }}
Webhook URL:
/api/webhooks/{{ g.provider }}/{{ tenant.slug }}
✓ Credenciales configuradas
⚠ Sin credenciales
{{ t.name }}
{{ t.token_prefix }}••••••••
{{ tokenModal.id ? 'Editar token' : 'Nuevo token' }}
Clientes activos
{{ kpis.clientes_activos || 0 }}
de {{ kpis.clientes_total || 0 }} totales
Contratos activos
{{ kpis.contratos_activos || 0 }}
{{ kpis.clientes_suspendidos || 0 }} suspendidos
ARPU mensual
PYG {{ fmt(kpis.arpu) }}
por contrato
Cobrado este mes
PYG {{ fmt(kpis.ingresos_mes_actual) }}
de PYG {{ fmt(kpis.facturacion_potencial_mensual) }} potencial
Por cobrar
PYG {{ fmt(kpis.deuda_total) }}
{{ kpis.tickets_abiertos || 0 }} tickets abiertos
Ingresos por mes (12 meses)
Distribución por plan
Distribución por ciudad
Top morosos
{{ topMorosos.length }} clientes con deuda| Cliente | Deuda | Atraso | Estado |
|---|---|---|---|
| {{ m.full_name }} | PYG {{ fmt(m.deuda) }} | {{ m.dias_de_atraso > 0 ? m.dias_de_atraso + 'd' : 'a tiempo' }} | {{ m.status }} |
Cobranza por método (30d)
Cobranza por cobrador (30d)
Zonas operativas con configuración de cobranza independiente
Cada zona puede tener su propio cobrador y días de gracia para mora
| Zona | Código | Contratos | Gracia mora | Cobrador | |
|---|---|---|---|---|---|
| {{ z.name }} | {{ z.code || '—' }} | {{ z.contratos_count }} | {{ z.dias_gracia_mora }}d default tenant | {{ z.cobrador_name || '—' }} |
Configuración de mora
Acciones masivas
| Nombre | Rol | Estado | ||
|---|---|---|---|---|
{{ initials(u.full_name) }} {{ u.full_name }} |
{{ u.email }} | {{ u.role }} | {{ u.is_active ? 'activo' : 'inactivo' }} |
{{ user.full_name }}
{{ user.email }}
{{ user.role }}Asignar ONU al cliente v2026-05-06b
Contrato: {{ addOnu.contrato_code }} · POP: {{ addOnu.concentrador }}
⚠ No hay OLTs vinculadas al concentrador "{{ addOnu.concentrador }}". Asignalas en Red → OLTs.
📡 ONUs detectadas (no autorizadas)
{{ addOnu.scanError }}
{{ it.sn }}
PON 0/{{ it.port }} · {{ it.vendor_id }}
Sin ONUs no autorizadas. Si la ONU ya fue autorizada antes, mirá la lista de abajo.
✅ ONUs ya autorizadas en la OLT
{{ addOnu.authError }}
{{ it.sn }} · ID {{ it.ont_id }}
PON 0/{{ it.port }} · estado {{ it.status || '?' }}
Sin ONUs autorizadas.
ONU seleccionada
{{ addOnu.onu.sn }}
PON 0/{{ addOnu.onu.port }} · ONT-ID {{ addOnu.onu.ont_id }} · {{ addOnu.onu.vendor_id }}
Rx
{{ addOnu.signalData.rx_dbm ?? '—' }} dBm
Tx
{{ addOnu.signalData.tx_dbm ?? '—' }} dBm
Distancia
{{ addOnu.signalData.distance_km ?? '—' }} km
Datos manuales
⛔ {{ addOnu.error }}
Nuevo cliente
Define la zona del cliente y filtra las OLTs disponibles para autorizar la ONU.
📡 Autorizar la ONU del cliente ahora (opcional).
Flujo recomendado: 1) elegí la OLT, 2) Escanear no autorizadas, 3) seleccioná la ONU del cliente.
⚠ No hay OLTs vinculadas a este concentrador. Andá a Red → OLTs y editá la OLT para asignarla.
ONUs no autorizadas en la OLT
{{ wizCli.scanError }}
{{ it.sn }}
slot {{ it.slot ?? 0 }} · port {{ it.port }} · pon {{ it.pon }} · {{ it.vendor }}
Sin ONUs no autorizadas detectadas. Si esperás una, verificá que esté encendida y conectada al PON.
Datos manuales (autocompletados al seleccionar arriba)
Line/Srv profile y VLAN se toman de los defaults de la OLT (Soluciones_Max / ser_1 / 101 en BTK).
⛔ {{ wizCli.error }}
⚠ Warnings:
- {{ w }}
{{ cliForm.id ? 'Editar cliente' : 'Nuevo cliente' }}
{{ perfil.cliente.full_name }}
{{ perfil.cliente.document_type }} {{ perfil.cliente.document_number }} · {{ perfil.cliente.city }}
Deuda total
PYG {{ fmt(perfil.deuda_total) }}
Contratos
{{ perfil.contratos.length }}
Pagos
{{ perfil.pagos.length }}
Datos
ONU
SN
{{ u.sn }}
{{ u.olt_name }} ({{ u.olt_vendor }}) · {{ u.slot }}/{{ u.port }}/{{ u.pon }} · ont {{ u.ont_id }}
Rx
{{ u.rx_dbm ?? '—' }} dBm
Tx
{{ u.tx_dbm ?? '—' }} dBm
Distancia
{{ u.distance_km ?? '—' }} km
Última lectura: {{ u.last_signal_at }}
Contratos ({{ perfil.contratos.length }})
{{ ct.code }}
{{ ct.plan_name || '—' }} +{{ fmt(ct.monto_extra) }} extra{{ fmt(ct.monto_extra) }} desc.
PPPoE usuario: {{ ct.pppoe_username }} · {{ ct.concentrador }}
Cargo extra / Descuento mensual
Sin ajuste — factura = precio del plan
+ Gs. {{ fmt(ct.monto_extra) }} (servicio adicional)
− Gs. {{ fmt(Math.abs(ct.monto_extra)) }} (descuento)
Cargo extra / Descuento mensual
Positivo = cargo adicional · Negativo = descuento · 0 = sin ajuste
Facturas ({{ perfil.facturas.length }})
{{ f.numero }}
{{ f.periodo }} · vence {{ f.fecha_vencimiento }}
PYG {{ fmt(f.saldo) }}
{{ f.status }}Pagos recientes
{{ p.numero_recibo }}
{{ p.fecha_pago }} · {{ p.metodo }}{{ p.referencia ? ' · ' + p.referencia : '' }}
ANULADOPYG {{ fmt(p.monto) }}
{{ contratoForm.id ? 'Editar contrato' : 'Nuevo contrato' }}
Cliente: {{ contratoForm.cliente_name }}
Define el Mikrotik donde se aprovisiona el PPPoE.
Positivo = cargo adicional (ej: 150000) · Negativo = descuento (ej: -20000) · 0 = sin ajuste
Total mensual: PYG {{ fmt((planes.find(p=>p.id===contratoForm.plan_id)?.price||0) + (contratoForm.monto_extra||0)) }}
💡 Al guardar, si cambia PPPoE username, plan, concentrador, password o status → se aprovisiona automáticamente en el Mikrotik.
Solo aparecen contratos con WA ON y deuda pendiente. Los checkboxes empiezan desmarcados — marcás vos a quién notificar.
Clientes elegibles
{{ notifElegibles.length }} disponibles {{ notifSeleccionados.length }} seleccionadosPara que un cliente aparezca aquí, activá WA ON en su contrato desde el perfil del cliente.
Preview de envío
{{ notifPreview.elegibles }}
Recibirán mensaje
{{ notifPreview.skipped }}
Skipped
{{ notifPreview.total_seleccionados }}
Total seleccionados
{{ item.cliente_full_name }}
{{ item.motivo_skip }}
Historial de envíos
{{ entry.numero_destino }}
{{ entry.tipo }} · {{ entry.created_at?.slice(0,16).replace('T',' ') }}
Cobrar {{ cobroModal.numero }}
Saldo: PYG {{ fmt(cobroModal.saldo) }}
📡 Apuntar {{ radiusModal.mikrotik_name }} al RADIUS
RADIUS server: {{ radiusModal.radius_server }} (FreeRADIUS dentro del VPS Konex)
{{ radiusModal.secret_created ? '🆕 Secret recién generado para este MK' : '🔑 Secret existente recuperado' }}
{{ radiusModal.notes }}
Shared secret
{{ radiusModal.shared_secret }}Script RouterOS
{{ radiusModal.routeros_script }}
¿Querés convivencia con TSMX RADIUS?
Sí. RouterOS prueba múltiples entries de /radius en orden por timeout. Konex queda primario, TSMX como fallback automático. NO borres el entry TSMX cuando agregues el de Konex.
💳 Promesa de pago
{{ promesaModal.cliente_full_name }} ({{ promesaModal.pppoe_username }})
Elegí cuánto durar la promesa:
Conectar Mikrotik
Subnets internas (LAN MK, gestión OLT) que KONEX debe alcanzar a través de este peer.
✓ Peer {{ vpnPeerCreated.peer.name }}
IP en túnel: {{ vpnPeerCreated.peer.assigned_ip }}
Password del usuario API konex
El script crea un usuario konex en el Mikrotik. Definí acá la contraseña que va a tener — la misma que después vas a poner en panel Konex → Editar MK → Test.
Script RouterOS 7.x
{{ (vpnPeerCreated.routeros_script || '').length }} caracteres{{ vpnPeerCreated.routeros_script }}
📌 Pegá esto en una New Terminal del Mikrotik. Idempotente — podés correrlo 2 veces.