Envío de recordatorios para la entrega de documentación

Cada cierto tiempo hay que revisar qué clientes no han entregado la documentación necesaria

⚙️ Make – Recepción periódica de facturas de clientes (Blueprint)

Este documento describe un diseño listo para implementar en Make (antes Integromat) para automatizar la recepción, clasificación y control de facturas (PDF/XML) recibidas por email. Incluye estructura de carpetas, esquema de Google Sheets, escenarios Make con módulos, filtros/routers, naming estándar, alertas y control de ausencias.


0) Prerrequisitos

  • Acceso/Conexiones en Make a: Gmail, Google Drive (o Dropbox), Google Sheets, (opcional) Slack.
  • Carpeta raíz en Drive: /Facturas/ (o la que elijas).
  • Google Sheet maestro: Control Facturas con 2 pestañas:
  • Clientes (tabla de correspondencia y plantilla esperada)
  • Recepciones (log de entradas)

Estructura de la pestaña Clientes

cliente_idcliente_nombreemails_permitidoscarpeta_drivedias_limiteplantilla_nombresfrecuencia
ACMEACME S.A.facturas@acme.com;contabilidad@acme.com/Facturas/ACME102025-01,2025-02,2025-03Mensual
  • emails_permitidos: lista separada por ; para filtrar remitentes.
  • carpeta_drive: ruta base del cliente (se crearán subcarpetas Año/Mes).
  • dias_limite: día del mes en el que se dispara la comprobación de faltantes.
  • plantilla_nombres: valores esperados por periodo (puede ser YYYY-MM o códigos que extraigas del archivo).

Estructura de la pestaña Recepciones

timestampcliente_idperiodoarchivo_originalnombre_estandartipoemail_idremitenteasuntourl_drivehash

1) Estructura de carpetas en Drive

/Facturas/
  ├── [Cliente]/
  │   ├── [Año]/
  │   │   └── [Mes-XX]/
  │   │       ├── PDF/
  │   │       └── XML/
  │   └── _INBOX/   (opcional, dumping temporal)
  └── _LOGS/
  • El escenario crea de forma perezosa (si no existe) cada nivel.

2) Estándar de nombres de archivo

Formato: {{cliente_id}}_{{periodo}}_{{emisorOpcional}}_{{consecutivoOpcional}}.{{ext}}

  • periodo: {{formatDate( fecha_invoice ?? fecha_email ; "YYYY-MM")}}
  • Ejemplo: ACME_2025-09_ProveedorX_000123.pdf

Reglas de saneado (Text aggregator/Replace):

  • Reemplazar espacios por _, eliminar tildes, caracteres /\\:*?"<>|#%&{}.

3) Escenario A – Ingesta y clasificación (evento: llegada de email)

Objetivo: Leer Gmail, descargar adjuntos PDF/XML, identificar cliente y período, renombrar y guardar en Drive, registrar en Sheets y alertar.

Módulos (en orden)

  1. Gmail > Watch emails
  • Carpeta/Etiqueta: Facturas Clientes (crea un filtro en Gmail que etiquete lo relevante) o query directa:
    • Query sugerida: label:"Facturas Clientes" has:attachment (filename:pdf OR filename:xml)
  • Marcado como Processed mediante etiqueta Make-Processed para evitar duplicados.
  1. Filters (Make) – Solo pasar si attachments[] contiene pdf o xml.
  2. Google Sheets > Search rows (tabla Clientes)
  • Buscar por remitente (From) en emails_permitidos o por cliente_nombre/código detectado en Asunto.
  • Si no hay match: Router ⇒ Rama «No identificado» (ver abajo).
  1. Routers
  • Rama OK (cliente identificado)
    1. Tools > Iterator sobre attachments[].
    2. Tools > Text parser para extraer periodo desde:
      • patrón en asunto (/(20\d{2})[-_ ]?(0[1-9]|1[0-2])/)
      • si no aparece, usar formatDate(now; "YYYY-MM").
    3. Google Drive > Create a folder (ensure) para /[cliente]/[Año]/[Mes-XX]/PDF|XML.
    4. Gmail > Get attachment (binario) del item.
    5. Tools > MD5 del binario ⇒ hash (deduplicación).
    6. Google Sheets > Search rows en Recepciones por hash o email_id+filename ⇒ si existe, saltar (evitar duplicados).
    7. Tools > Text aggregator/Replace para construir nombre_estandar.
    8. Google Drive > Upload a file a carpeta PDF o XML según extensión.
    9. Google Sheets > Add a row a Recepciones con todos los campos.
    10. Slack/Email > Notify al canal interno.
  • Rama No identificado
    • Gmail > Add label Facturas-Revision
    • Slack/Email para revisión manual con enlace al email.
  1. Gmail > Add label Make-Processed al hilo (idempotencia).

Filtros clave (ejemplos)

  • Adjuntos válidos: lower(attachments[].mimeType) contains "pdf" OR contains "xml"
  • Remitente permitido: find(regexp; emails_permitidos; from)
  • Duplicado: exists( row.hash == current.hash )

4) Escenario B – Reconciliación mensual (programado)

Objetivo: Comparar lo recibido vs. lo esperado y avisar faltantes.

Disparador

  • Scheduler: cada día {{dias_limite}} a las 08:00 (zona Europe/Madrid).

Flujo

  1. Google Sheets > Get rows (Clientes)
  2. Iterator por cliente
  3. Tools > Build periodperiodo_actual = formatDate( addMonths(now; -1) ; "YYYY-MM") (si se reconcilia el mes anterior)
  4. Google Sheets > Search rows (Recepciones) por cliente_id + periodo_actual ⇒ lista de recibidas.
  5. Calcular faltantes: comparar contra plantilla_nombres (split por ,).
  6. Routers
  • Si faltantes > 0
    • Email (Gmail > Send email) al cliente (CC interno) con tabla de faltantes y enlace a carpeta del período.
    • Sheets > Add rows a Recepciones con estado Pendiente (opcional tracking).
  • Si 0Slack/Email confirmación de cierre de período.

Sugerencia de cuerpo de email (HTML)

Asunto: [{{cliente_nombre}}] Facturas faltantes {{periodo_actual}}

Hola {{contacto}},
Revisando la documentación de {{periodo_actual}}, faltan las siguientes facturas:
{{tabla_faltantes_html}}
Puedes subirlas directamente aquí: {{url_carpeta_periodo}}
Gracias.

5) Manejo de errores y calidad de datos

  • Try/Catch con rutas de error en Make para:
  • Adjuntos corruptos o sin permisos ⇒ mover a _INBOX y avisar.
  • Colisiones de nombre ⇒ añadir sufijo __dup{{now}}.
  • Idempotencia: etiqueta Make-Processed + hash en Recepciones.
  • Trazabilidad: guardar email_id, asunto, remitente, url_drive.

6) Variantes / Extensiones

  • Dropbox en lugar de Drive: sustituir módulos de almacenamiento.
  • OCR (Make + Google Drive/Cloud Vision) para extraer fecha y importe y poblar columnas extra.
  • Validación contra ERP: conector HTTP al ERP para marcar recepción.

7) Expresiones útiles (Make)

  • formatDate(now; "YYYY-MM")
  • formatDate(parseDate(email.date; "RFC_2822"); "YYYY-MM")
  • Regex periodo en asunto: /(20\d{2})[-_ ]?(0[1-9]|1[0-2])/
  • Saneado de texto (ejemplo):
  • Reemplazar espacios: replace(text; " "; "_")
  • Quitar tildes: replace(diacritics(text); ""; "")
  • Limpiar caracteres: replaceRegex(text; "[\\\\/\\:*?\"<>|#%&{}]"; "")

8) Blueprint JSON (plantilla para importar en Make)

⚠️ Nota: Sustituye {{CONNECTION_ID_*}} y {{SPREADSHEET_ID}} por tus valores. Es un esqueleto funcional para que ajustes rutas/IDs.

{
  "name": "Recepción de facturas – Ingesta y clasificación",
  "flow": [
    { "module": "gmail.watchEmails", "name": "Watch emails", "config": { "query": "label:'Facturas Clientes' has:attachment (filename:pdf OR filename:xml)", "markAsRead": false } },
    { "module": "tools.filter", "name": "Adjuntos válidos", "condition": "lower(map(attachments; item.mimeType)) contains 'pdf' or contains 'xml'" },
    { "module": "googlesheets.searchRows", "name": "Buscar cliente por remitente", "config": { "spreadsheetId": "{{SPREADSHEET_ID}}", "sheet": "Clientes", "criteria": { "emails_permitidos": "{{from}}" } } },
    { "module": "router", "name": "Router cliente" },
    { "module": "tools.iterator", "name": "Iterar adjuntos" },
    { "module": "tools.regex", "name": "Extraer periodo", "pattern": "(20\\d{2})[-_ ]?(0[1-9]|1[0-2])" },
    { "module": "googledrive.ensureFolder", "name": "Asegurar carpeta periodo", "path": "{{carpeta_drive}}/{{match.1}}/{{match.2}}" },
    { "module": "gmail.getAttachment", "name": "Descargar adjunto" },
    { "module": "tools.md5", "name": "Hash binario" },
    { "module": "googlesheets.searchRows", "name": "Deduplicación por hash", "config": { "spreadsheetId": "{{SPREADSHEET_ID}}", "sheet": "Recepciones", "criteria": { "hash": "{{hash}}" } } },
    { "module": "tools.text", "name": "Construir nombre estandar" },
    { "module": "googledrive.uploadFile", "name": "Subir a Drive", "path": "{{carpeta_periodo}}/{{ext == 'pdf' ? 'PDF' : 'XML'}}/{{nombre_estandar}}" },
    { "module": "googlesheets.addRow", "name": "Registrar recepción", "config": { "spreadsheetId": "{{SPREADSHEET_ID}}", "sheet": "Recepciones" } },
    { "module": "gmail.addLabel", "name": "Marcar procesado", "label": "Make-Processed" }
  ],
  "connections": {
    "gmail": "{{CONNECTION_ID_GMAIL}}",
    "googledrive": "{{CONNECTION_ID_DRIVE}}",
    "googlesheets": "{{CONNECTION_ID_SHEETS}}"
  }
}

9) Pruebas y despliegue

  1. Sandbox: activa el escenario con un filtro adicional subject contains 'TEST'.
  2. Envía 3 emails de prueba (PDF y XML, remitentes válidos y no válidos).
  3. Verifica:
  • Creación de carpetas y nombres.
  • Registro en Recepciones (sin duplicados).
  • Etiquetado Make-Processed en Gmail.
  1. Retira el filtro TEST y activa en producción.

10) Mantenimiento

  • Revisa mensualmente la pestaña Clientes (nuevos remitentes, cambios de carpeta).
  • Reentrena regex si cambia el patrón de asunto.
  • Archiva la pestaña Recepciones por año para rendimiento.

11) Snippets de mapeo (copiar/pegar en Make)

  • Periodo fallback:
  • if( length( regex(search: subject; pattern: "(20\\d{2})[-_ ]?(0[1-9]|1[0-2])") ) > 0; join( regex(...); "-"); formatDate(now; "YYYY-MM") )
  • Ruta periodo:
  • {{carpeta_drive}}/{{split(periodo; "-")[0]}}/{{split(periodo; "-")[1]}}
  • Nombre estándar:
  • replaceRegex(replace(diacritics(concat(cliente_id; "_"; periodo; "_"; filenameBase; "."; ext)); "[\\\\/\\:*?\"<>|#%&{}]"; ""); " "; "_")

✅ Resultado

  • Archivos guardados y nombrados automáticamente en Drive por cliente y mes.
  • Registro fiable en Sheets con deduplicación por hash.
  • Alertas automáticas por faltantes en la fecha objetivo.