fix: seguridad del webhook de soporte, pagos en contabilidad y Telegram para tareas

- soporte: el webhook de correo entrante era público sin ninguna validación;
  ahora exige una API key (query ?key= o header) comparada en tiempo constante.
  Además evita tickets duplicados por reintentos del proveedor (dedup por
  Message-Id) y enhebra respuestas del mismo remitente en vez de abrir un
  ticket nuevo por cada correo.
- contabilidad: marcar una cuenta por cobrar/pagar como pagada ahora crea y
  vincula la Transaccion correspondiente (antes el dashboard de ingresos/
  egresos nunca reflejaba esos pagos). Se corrige además que actualizar una
  cuenta por cobrar borraba su transaccion_id en cada PUT.
- tareas: se activa por defecto el canal Telegram para tarea_asignada (estaba
  apagado desde el seed original) y se agrega un flujo real de vinculación de
  Telegram para el staff interno (código temporal + verificación), igual al
  que ya existía para los usuarios del portal — sin esto el chat_id de cada
  usuario había que pegarlo a mano y la notificación nunca llegaba.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Lizandro GD
2026-08-03 01:25:17 +00:00
co-authored by Claude Sonnet 5
parent 1127d944c7
commit d2bf699b60
14 changed files with 612 additions and 100 deletions
@@ -494,6 +494,31 @@ func DeleteCuentaCobro(c *fiber.Ctx) error {
return c.JSON(fiber.Map{"ok": true})
}
// MarcarCuentaCobroPagada registra el pago y crea la transacción de ingreso vinculada.
// POST /contabilidad/cuentas-cobro/:id/pagar
func MarcarCuentaCobroPagada(c *fiber.Ctx) error {
id, err := strconv.ParseUint(c.Params("id"), 10, 32)
if err != nil {
return c.Status(400).JSON(fiber.Map{"error": "ID inválido"})
}
var req struct {
FechaPago string `json:"fecha_pago"`
}
if err := c.BodyParser(&req); err != nil {
return c.Status(400).JSON(fiber.Map{"error": err.Error()})
}
fecha := time.Now()
if req.FechaPago != "" {
if parsed, err := time.Parse("2006-01-02", req.FechaPago); err == nil {
fecha = parsed
}
}
if err := models.MarcarCuentaCobroPagada(uint(id), fecha); err != nil {
return c.Status(500).JSON(fiber.Map{"error": err.Error()})
}
return c.JSON(fiber.Map{"ok": true})
}
// =============================================================================
// ─── CRUD: Cuentas por Pagar ────────────────────────────────────────────────
// =============================================================================