Commit Graph
21 Commits
Author SHA1 Message Date
Lizandro GuarnizoandClaude Sonnet 5 023a8af494 feat(cobro): suma el consumo de uMind al ciclo de cobro existente
El cobro recurrente (link de pago, webhook con firma, renovación
automática de vencimiento) ya funcionaba de punta a punta; lo único que
le faltaba para cobrar por uso era monto variable.

- MontoACobrar = PrecioAcordado + consumo pendiente del cliente. Si el
  cliente no usa uMind el consumo es 0 y el monto queda idéntico al de
  antes, así que los contratos existentes no cambian.
- El consumo se agrega por Cliente, no por tenant: un contrato es de un
  cliente y un cliente puede tener varios tenants.
- El desglose (cuántos tokens, imágenes y transcripciones, y a cuánto)
  va como líneas de servicio, así las plantillas de correo existentes lo
  muestran sin tocarlas. Cobrar un monto variable sin decir de dónde sale
  es pedir una disputa.
- Al confirmarse el pago se cierra el consumo (facturado_at). Solo si el
  UPDATE del contrato afectó filas: si el webhook llega dos veces, la
  segunda no vuelve a cerrar nada.
- Test de que el detalle del correo suma exactamente lo que se cobra.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-13 11:53:40 -05:00
Lizandro GDandClaude Opus 5 c8e5afceb2 fix: seguridad de pagos y accesos, integración PayPal y Coolify ampliado
Seguridad (crítico):
- Los webhooks de Bold y dLocal solo validaban la firma si el atacante la
  enviaba: sin cabecera se aceptaba cualquier payload. Ahora es obligatoria.
- GET /pago-exitoso marcaba contratos como pagados leyendo un query param del
  navegador. Ahora solo muestra estado; la confirmación la hace la verificación
  contra la API de la pasarela o el webhook firmado.
- /uploads se servía como estático público: se descargaban RUTs, facturas y
  entregables sabiendo la ruta. Ahora exige sesión.
- Los secretos JWT no se podían sobreescribir por entorno (faltaba el tag env:)
  y su valor estaba en el repo, permitiendo firmarse una sesión de admin. Ahora
  son configurables y el arranque se detiene si siguen con el valor publicado.
- .env y session.db salen del control de versiones.
- Query Runner, gestión de usuarios/roles/módulos y seeds quedan restringidos a
  administradores; antes bastaba con tener sesión.

Pasarelas de pago:
- dLocal generaba enlaces que nunca se reconciliaban: mandaba el ID numérico en
  vez de "contrato-N", la URL de retorno apuntaba a la API de dLocal y nunca se
  enviaba notification_url, así que su webhook jamás se disparaba.
- PayPal solo tenía pantalla de configuración. Se implementa el servicio
  completo (OAuth, orden, captura, verificación de webhook) y queda
  seleccionable como pasarela.
- La moneda estaba fija en COP: un contrato en USD generaba un cobro por esa
  cifra en pesos.

Contratos:
- pago_confirmado nunca volvía a false, así que el segundo ciclo de renovación
  no se cobraba aunque el cliente pagara. Se reinicia al generar enlace nuevo.
- Los contratos vencidos nunca cambiaban de estado y recibían correo a diario
  de forma indefinida; ahora se cierran tras 30 días de gracia.

Otros:
- Coolify: coolifyCall ignoraba el status HTTP y reportaba errores como éxito.
  El agente pasa de 10 a cobertura completa (servicios, bases de datos,
  variables de entorno, proyectos, equipos y recursos de servidor).
- SeedBalanceData ya no corre en cada arranque (recreaba transacciones
  borradas); ahora se invoca con SEED_BALANCE=1.
- Los seeds dejan de devolver permisos revocados en cada despliegue.
- Timeouts en las llamadas HTTP a Telegram y dLocal que podían colgarse.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-03 03:20:00 +00:00
Lizandro GuarnizoandClaude Sonnet 4.6 b3b6f6705d fix: marcar pago manual no toca estado ni fecha_vencimiento
MarcarContratoPagado siempre sobreescribía estado='activo' y renovaba
fecha_vencimiento, lo que causaba doble renovación si el admin ya había
ajustado el contrato manualmente. ConfirmarPagoManual solo limpia
pago_confirmado, fecha_pago y el enlace Bold, sin tocar nada más.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-09 20:13:40 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 dfe8d9e4a9 fix: columna FK incorrecta en contrato_servidores y filtrado de BDs en modal
- syncContratoJoin derivaba "contrato_servidore_id" en vez de "servidor_id"
  al recortar el último carácter del nombre de tabla; ahora usa TrimPrefix+TrimSuffix
  para derivar correctamente servidor_id, conx_db_id, ai_config_id
- Modal contratos: filteredConxDbList filtra BDs por servidor(es) seleccionado(s)
  en vez de mostrar todas las BDs sin contexto

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-09 11:58:01 -05:00
Lizandro Guarnizo 478c2bde00 up 2026-06-10 00:18:20 -05:00
Lizandro Guarnizo 7329bac898 up 2026-06-04 22:49:16 -05:00
Lizandro Guarnizo 61b3eca31d up 2026-05-14 22:30:31 -05:00
Lizandro Guarnizo ce2fed2587 up 2026-05-13 22:36:09 -05:00
Lizandro Guarnizo 381425b7e6 ip 2026-05-12 22:34:10 -05:00
Lizandro Guarnizo 9ca202b3bd up 2026-05-12 21:33:54 -05:00
Lizandro Guarnizo fbd75d8cc6 up 2026-05-12 21:22:30 -05:00
Lizandro Guarnizo 217e1b550f up 2026-05-12 20:41:50 -05:00
Lizandro Guarnizo 05141ce70e up 2026-05-12 18:53:09 -05:00
Lizandro Guarnizo 387485e65b up 2026-05-12 18:34:20 -05:00
Lizandro Guarnizo c9024274f0 up 2026-05-01 17:36:17 -05:00
Lizandro Guarnizo 3f6eb7dddc p 2026-05-01 13:44:37 -05:00
Lizandro Guarnizo 5e0b6ae2f0 up 2026-05-01 12:02:21 -05:00
Lizandro Guarnizo 92ef6d48e8 fix: usar SQL directo en join table contrato_servicios para evitar upsert de GORM 2026-04-30 22:24:26 -05:00
Lizandro Guarnizo e751a9f894 feat: contrato soporta múltiples servicios (many2many) con precio sugerido 2026-04-30 22:15:31 -05:00
Lizandro Guarnizo 1b0374204c fix: usar Updates(map) en lugar de Updates(struct) para evitar error id en PostgreSQL 2026-04-30 22:01:12 -05:00
Lizandro Guarnizo f787821444 up 2026-04-29 23:36:30 -05:00