CreaRack-SL

Endpoints vínculos task ↔ Zoho Calendar (GET/POST/DELETE /api/tasks/{id}/links/calendar)

Endpoints vínculos task ↔ Zoho Calendar

functions/api/tasks/[id]/links/calendar.ts — añadido en s68 (commit 7617371, 2026-05-17).

Persiste en D1 las referencias locales a eventos de Zoho Calendar creados desde TaskModal. El evento real vive en Zoho; esta tabla es el registro de vínculos.

Endpoints

GET /api/tasks/{id}/links/calendar

Lista todos los eventos vinculados a la task ordenados por created_at DESC.

Respuesta 200:

[
  {
    "task_id": 42,
    "zoho_event_uid": "abc123",
    "calendar_uid": "cal456",
    "title": "Revisión presupuesto Rack A",
    "start_at": "2026-05-20T10:00:00Z",
    "end_at": "2026-05-20T11:00:00Z",
    "url": "https://calendar.zoho.eu/",
    "created_by": "Edu",
    "created_at": "2026-05-17T10:30:00"
  }
]

POST /api/tasks/{id}/links/calendar

Crea un vínculo entre la task y un evento ya existente en Zoho (típicamente llamado justo después de POST /api/zoho/calendar).

Body requerido:

{
  "zoho_event_uid": "string",
  "calendar_uid": "string",
  "title": "string (opcional)",
  "start_at": "ISO string (opcional)",
  "end_at": "ISO string (opcional)",
  "url": "string (opcional)"
}

Autenticación: requiere CF Access. created_by = TeamMember resuelto vía resolveTeamMember(request).

Conflicto: ON CONFLICT(task_id, zoho_event_uid) DO UPDATE — actualiza metadatos si el mismo evento se vincula dos veces.

Respuesta 201: el row insertado/actualizado.

Errores:

  • 400 — task_id inválido o campos requeridos ausentes.
  • 403 — actor no identificado como TeamMember.
  • 404 — task no encontrada en D1.

DELETE /api/tasks/{id}/links/calendar?uid={zoho_event_uid}

Elimina el vínculo (no borra el evento en Zoho).

Query param requerido: uid = zoho_event_uid.

Respuesta 200: { "deleted": 1 } (o 0 si no existía).

Tabla D1: task_calendar_events

CREATE TABLE task_calendar_events (
  task_id          INTEGER NOT NULL REFERENCES tasks(id),
  zoho_event_uid   TEXT NOT NULL,
  calendar_uid     TEXT NOT NULL,
  title            TEXT,
  start_at         TEXT,
  end_at           TEXT,
  url              TEXT,
  created_by       TEXT NOT NULL,  -- TeamMember
  created_at       TEXT DEFAULT (datetime('now')),
  PRIMARY KEY (task_id, zoho_event_uid)
);

Creada en Migration 0027.

Integración con GET /api/tasks

El listado de tasks incluye calendar_event_count calculado en SQL:

(SELECT COUNT(*) FROM task_calendar_events WHERE task_id = tasks.id) AS calendar_event_count

Esto permite a KanbanMini, TaskTableView y TaskCalendar mostrar badges sin round-trip adicional.

Flujo típico desde TaskModal

Usuario clicka "Crear evento" en TaskZohoLinks
  → POST /api/zoho/calendar  { title, start, end, attendees }
  ← { uid, calendar_uid, url }
  → POST /api/tasks/{id}/links/calendar  { zoho_event_uid: uid, calendar_uid, ... }
  ← 201 LinkRow
  → TaskZohoLinks re-fetchea GET /api/tasks/{id}/links/calendar

Véase también

  • [[entity—workers—endpoint—task-email-links]]
  • [[entity—workers—service—zoho-lib]]
  • [[entity—workers—service—staff-lib]]
  • [[feature—zoho—per-user-oauth]]
  • [[decision—20260517—integracion-zoho-calendar-mail-pivot]]