Skip to content

TODO — Pendiente de aprobación ​

Recursos que NO se migran en la primera corrida y quedan a la espera de decisión del cliente / lead técnico.

1. Meetings / Appointments / Calendars / Calendar Events ​

Estado: ❌ Pausado.

Por qué se sacó del scope inicial:

  • El modelo meetings del destino está pensado alrededor de Google Calendar (campos google_event_id, google_meet_link, google_calendar_id, synced, synced_at). En GHL los appointments viven dentro de su propio sistema de booking — no hay un Google Calendar Event ID que mapear.
  • Hay que decidir si:
    1. Migrar appointments sin Google sync y dejar synced=false (los usuarios re-conectarían su Google después en imcrmdev).
    2. No migrar histórico y arrancar limpio.
    3. Migrar solo eventos futuros (a partir de hoy) y descartar el histórico.
  • También falta saber si Trebol usa el módulo de citas activamente (volumen real, importancia para retención de cliente).

Lo que queda en pausa:

Recurso GHLEndpointDestino propuesto
Calendarios (catálogo)GET /calendars/?locationId=…calendars (NUEVA)
Calendar Events (rango)GET /calendars/events?calendarId=…&startTime=…&endTime=…meetings
Appointments por contactoGET /contacts/{id}/appointmentsmeetings

Mapping propuesto (cuando se apruebe) ​

Calendar (calendars — NUEVA) ​

OrigenDestino
idexternal_id
namename
descriptiondescription
calendarTypecalendar_type
eventTypeevent_type
slotDurationslot_duration
teamMembers[]team_members[]
widgetSlugwidget_slug

Appointment / Calendar Event (meetings) ​

OrigenDestinoNota
idexternal_id
titletitle
notes o descriptiondescription
startTimestart_timeparse ISO
endTimeend_timeparse ISO
addresslocation
appointmentStatusstatusmapear: confirmed→confirmed, cancelled→cancelled, noshow→no_show, default → scheduled
assignedUserIdowner_user_idresolver a users._id destino
contactIdcontact_idresolver a contacts_new._id destino
calendarIdcustom_fields.calendar_idpreserva FK lógica
dateAddedcreated_at
dateUpdatedupdated_at
—google_event_idvacío (no aplica)
—google_meet_linkvacío
—google_calendar_idvacío
—syncedfalse (forzado)
—attendees[]array vacío (GHL no expone igual)

Decisiones que necesitamos antes de arrancar ​

  • [ ] ¿Migra histórico, solo futuro, o nada?
  • [ ] Si migra histórico, ¿cuántos años atrás? (recomendación: 1 año)
  • [ ] ¿Los usuarios van a re-conectar Google Calendar manualmente en imcrmdev, o es deal-breaker tener sync inmediato?
  • [ ] ¿Hay que enviar notificaciones (reminders_sent[]) post-migración? (Recomendación: NO, son citas pasadas)

2. Custom Field Definitions (catálogo en colección propia) ​

Estado: ❌ Pausado (la persistencia del catálogo). El uso interno sí se mantiene — explicación abajo.

¿Qué es un Custom Field Definition? ​

En GHL, un Custom Field es un campo extra que se agrega a un contacto, oportunidad u otro objeto. Por ejemplo, para Trebol probablemente existen:

  • "Bank Name" (texto)
  • "Comments & Questions" (texto largo)
  • "B-018-GLB. SMS Opt-Out Date" (fecha)
  • "Gender" (single option: Male/Female)
  • etc.

Trebol tiene 227 custom field definitions.

Cada definición dice: "este campo se llama X, es de tipo TEXTO/FECHA/NÚMERO/RADIO, su key interna es contact.bank_name, va en la posición 50 del formulario, etc."

Cada contacto tiene un array customFields: [{id, value}] donde id es el id de la definición y value es el valor para ese contacto.

Por qué se sacó al TODO ​

La pregunta abierta es: ¿queremos que imcrmdev replique el concepto de "custom fields" como entidad de primera clase?

  • Si SÍ: necesitamos una colección custom_field_definitions (con tipo, opciones de picklist, posición en el form) para que el frontend pueda renderizar formularios dinámicos por tenant. Hoy imcrmdev no tiene este concepto — los custom_fields en contacts_new son un objeto libre tipo {key: value} sin metadatos.
  • Si NO: los valores quedan guardados en contacts_new.custom_fields como objeto libre (que es lo que el script ya hace), pero el frontend no sabe que "bank_name" debe renderizarse como texto y "gender" como select.

Esta decisión es de producto, no de migración.

Lo que el script SÍ hace en este momento ​

Aunque NO persiste el catálogo en Mongo, el script igual lee las 227 definiciones de GHL en memoria al arrancar (ctx.custom_field_map). Eso lo necesitamos para resolver:

js
// GHL devuelve esto en cada contacto:
{ "customFields": [{ "id": "0QstDUndlPhfmKoKoD3k", "value": "Bank of America" }] }

// El script lo guarda en Mongo así:
{ "custom_fields": { "bank_name": "Bank of America" } }
//                    ↑ resuelto desde la definición

Sin la lectura de definiciones, las keys quedarían como 0QstDUndlPhfmKoKoD3k — ilegibles.

Por eso el script:

  • ✅ Sigue llamando GET /locations/{id}/customFields al arrancar
  • ✅ Sigue resolviendo id → fieldKey para los contactos y oportunidades
  • ❌ NO escribe la colección custom_field_definitions en Mongo

Cuando producto decida, agregar la persistencia es un cambio de 5 líneas (re-activar el bulk_upsert en migrate_custom_fields).

Decisiones que necesitamos ​

  • [ ] ¿imcrmdev va a soportar custom fields como concepto de producto? (admin UI para crearlos, formularios dinámicos)
  • [ ] Si sí, ¿el modelo de datos es por-tenant (company_id + field_key) o global?
  • [ ] ¿Mantener el concepto de folders (parentId) para agrupar campos en la UI?

Mapping propuesto (cuando se apruebe) ​

custom_field_definitions (NUEVA) ​

Origen GHLDestino
idexternal_id
namename
fieldKeyfield_key
placeholderplaceholder
dataTypedata_type (TEXT, LARGE_TEXT, NUMERICAL, DATE, MONETORY, CHECKBOX, RADIO, SINGLE_OPTIONS, MULTIPLE_OPTIONS, FILE_UPLOAD, SIGNATURE)
positionposition
documentTypedocument_type
parentIdfolder_id
modelmodel (contact, opportunity, etc.)
picklistOptions[]options[]
standardstandard
dateAddedcreated_at