Konexia

Gestión ISP · Konex

{{ loginError }}

Konexia · SaaS multi-tenant · {{ new Date().getFullYear() }}

Konexia · {{ tenant.name }}

{{ tabLabel }}

ClienteEstado
{{ initials(c.full_name) }}

{{ c.full_name }}

{{ c.document_number }}

{{ c.status }}
{{ clientes.loading ? 'Cargando...' : 'Sin clientes' }}
{{ clientes.total }} clientes · página {{ clientes.page }}
ClienteMontoSaldo
{{ initials(f.cliente_nombre) }}

{{ f.cliente_nombre || '—' }}

{{ f.cliente_doc }} · {{ f.numero }}

PYG {{ fmt(f.monto) }} PYG {{ fmt(f.saldo) }}
Sin facturas
{{ facturas.total }} 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) }}

Sin deudas pendientes ✨

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 }}

Sin Mikrotiks

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 }}

Sin conexiones. Agregá una WG para alcanzar las OLTs detrás del NAT del ISP.

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 }}

Sin OLTs. Agregá una para autorizar ONUs desde el panel.

{{ onus.total }} ONUs autorizadas

SNRx (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) }}

{{ p.is_active ? 'activo' : 'inactivo' }}

Bajada

{{ p.download_mbps }} Mbps

Subida

{{ p.upload_mbps }} Mbps

Profile Mikrotik: {{ p.profile_name || '—' }}

{{ g.name }}

Provider: {{ g.provider }} · {{ g.mode }}

{{ g.is_active ? 'activo' : 'inactivo' }} por defecto

Webhook URL:

/api/webhooks/{{ g.provider }}/{{ tenant.slug }}

✓ Credenciales configuradas

⚠ Sin credenciales

Sin pasarelas. Agregá una para que tus clientes puedan pagar online desde la PWA.
Cargando...

{{ t.name }}

{{ t.token_prefix }}••••••••

{{ t.is_active ? 'activo' : 'inactivo' }} ⚠ VENCIDO vence {{ new Date(t.expires_at).toLocaleDateString('es-PY') }} sin vencimiento
Scopes: {{ t.scopes }} Usos: {{ t.requests_count }} Último uso: {{ new Date(t.last_used_at).toLocaleString('es-PY') }}
Sin tokens configurados.

{{ 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

{{ d.plan }}{{ d.cantidad }} ({{ d.porcentaje }}%)

Distribución por ciudad

{{ c.ciudad }} {{ c.cantidad }}

Top morosos

{{ topMorosos.length }} clientes con deuda
ClienteDeudaAtrasoEstado
{{ 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)

{{ m.metodo }}PYG {{ fmt(m.total) }} ({{ m.cantidad }})
Sin pagos

Cobranza por cobrador (30d)

{{ c.cobrador }}PYG {{ fmt(c.total) }} ({{ c.cantidad }})
Sin pagos

Zonas operativas con configuración de cobranza independiente

Cada zona puede tener su propio cobrador y días de gracia para mora

ZonaCódigoContratosGracia moraCobrador
{{ z.name }} {{ z.code || '—' }} {{ z.contratos_count }} {{ z.dias_gracia_mora }}d default tenant {{ z.cobrador_name || '—' }}

Configuración de mora

Acciones masivas

Corrige disabled=false en suspendidos/morosos
{{ opsResult }}
NombreEmailRolEstado
{{ initials(u.full_name) }}
{{ u.full_name }}
{{ u.email }} {{ u.role }} {{ u.is_active ? 'activo' : 'inactivo' }}
{{ initials(user.full_name) }}

{{ user.full_name }}

{{ user.email }}

{{ user.role }}
Tenant{{ tenant.name }}
Plan SaaS{{ tenant.plan || '—' }}
Agente IA{{ 'Konex' }}

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 }}

✓ seleccionada click

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 || '?' }}

vincular

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

1 · Datos personales
2 · Servicio
3 · ONU (opcional)

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 }}

✓ seleccionada

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' }}

{{ initials(perfil.cliente.full_name) }}

{{ 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

Tel{{ perfil.cliente.phone || '—' }}WA{{ perfil.cliente.whatsapp || '—' }}Email{{ perfil.cliente.email || '—' }}Dirección{{ perfil.cliente.address || '—' }}Ciudad{{ perfil.cliente.city || '—' }}Depto{{ perfil.cliente.department || '—' }}

ONU

SN

{{ u.sn }}

{{ u.olt_name }} ({{ u.olt_vendor }}) · {{ u.slot }}/{{ u.port }}/{{ u.pon }} · ont {{ u.ont_id }}

{{ u.status }}

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 }}

contraseña: •••••••• {{ ppShown[ct.id] }}
{{ ct.status }}
🛡️ Promesa activa hasta {{ promesaActiva[ct.id].fecha_promesa }} — no se suspende.

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 }}
Sin facturas ·

Pagos recientes

{{ p.numero_recibo }}

{{ p.fecha_pago }} · {{ p.metodo }}{{ p.referencia ? ' · ' + p.referencia : '' }}

ANULADO

PYG {{ fmt(p.monto) }}

Sin pagos registrados

{{ 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 }} seleccionados
Cargando...
No hay clientes elegibles en esta zona.
Para 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.elegible ? '✅' : '⏭' }}

{{ item.cliente_full_name }}

{{ item.motivo_skip }}

Gs. {{ fmt(item.saldo_total) }}
⚠️ Se enviará 1 mensaje por cliente con pausa aleatoria entre envíos (anti-baneo). El proceso puede tardar varios minutos si hay muchos clientes.

Historial de envíos

Sin envíos registrados
{{ entry.estado==='sent' ? '✓' : entry.estado==='failed' ? '✗' : '—' }}

{{ entry.numero_destino }}

{{ entry.tipo }} · {{ entry.created_at?.slice(0,16).replace('T',' ') }}

Gs. {{ fmt(entry.monto) }} {{ entry.motivo_skip }}

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 }})

Saldo actualPYG {{ fmt(promesaModal.saldo_total) }}

Elegí cuánto durar la promesa:

🛡️ El cliente no se suspende hasta el {{ promesaModal.fecha_promesa }}. Si ya hay otra promesa activa, se reemplaza.

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.

{{ mtForm.id ? 'Editar Mikrotik' : 'Nuevo Mikrotik' }}

{{ planForm.id ? 'Editar plan' : 'Nuevo plan' }}

{{ userForm.id ? 'Editar usuario' : 'Nuevo usuario' }}

{{ gwForm.id ? 'Editar pasarela' : 'Nueva pasarela' }}

{{ zonaForm.id ? 'Editar zona' : 'Nueva zona' }}

{{ toast.msg }}

Editar factura

{{ facturaEditModal.numero }}

Nueva conexión

Para alcanzar OLTs/equipos detrás del NAT del ISP, Konex usa un túnel WireGuard. El ISP carga el .conf en su Mikrotik.

{{ connModal.error }}

{{ connConfig.name }}

IP del peer: {{ connConfig.peer_ip }} · Endpoint: {{ connConfig.endpoint }}

QR para WireGuard mobile

Config para Mikrotik / linux

{{ connConfig.config }}

{{ oltModal.id ? 'Editar OLT' : 'Agregar OLT' }}

Si no estás seguro, dejá uno cualquiera y usá Probar después de guardar — KONEX detecta el banner.

Define la zona. KONEX solo ofrecerá esta OLT a clientes del mismo POP.

{{ oltModal.error }}

Perfiles detectados — {{ oltDetect.oltName }}

Line profiles ({{ oltDetect.line.length }})

  • {{ p.name }}
  • — vacío —

Service profiles ({{ oltDetect.srv.length }})

  • {{ p.name }}
  • — vacío —

Autorizar ONU — {{ onuWizard.olt?.name }}

Seleccioná una ONU detectada (sin autorizar):

SNSlot/PortVendor
{{ u.sn }} {{ u.slot }}/{{ u.port }} {{ u.vendor_id }}
No hay ONUs sin autorizar (o el comando no se reconoce)

{{ onuWizard.error }}

SN: {{ onuWizard.selected.sn }}

Slot/Port: {{ onuWizard.selected.slot }}/{{ onuWizard.selected.port }}

{{ c.full_name }} {{ c.document_number }}

→ Vinculará a contrato del cliente seleccionado

{{ onuWizard.error }}