From fb28140e23f1c8f840a8096d06947f3d6597d06b Mon Sep 17 00:00:00 2001 From: Lizandro Guarnizo <77708265+lizandrogd@users.noreply.github.com> Date: Tue, 30 Jun 2026 09:03:01 -0500 Subject: [PATCH] =?UTF-8?q?docs:=20API=20spec=20for=20ERP=20Palmas360=20?= =?UTF-8?q?=E2=80=94=20all=2016=20endpoints=20documented?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Complete endpoint specification for the ERP team: - 10 GET (download) endpoints returning PDF/Excel files - 6 POST (upload) endpoints receiving WhatsApp form data - Auth headers, request/response schemas, and endpoint_key mapping table Co-Authored-By: Claude Sonnet 4.6 --- API-ERP-PALMAS360.md | 497 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 497 insertions(+) create mode 100644 API-ERP-PALMAS360.md diff --git a/API-ERP-PALMAS360.md b/API-ERP-PALMAS360.md new file mode 100644 index 0000000..1cd229f --- /dev/null +++ b/API-ERP-PALMAS360.md @@ -0,0 +1,497 @@ +# Especificación de Endpoints — ERP Palmas360 ↔ Bot WhatsApp + +> **Para el equipo de Palmas360:** Este documento describe todos los endpoints que el ERP debe implementar para que el bot de WhatsApp funcione correctamente. Los endpoints marcados con ⚠️ actualmente apuntan a URLs de prueba (`httpbin.org/post`) y deben ser reemplazados con las URLs reales del ERP. + +--- + +## Autenticación + +Todas las llamadas del bot al ERP incluyen dos headers de autenticación: + +``` +Authorization: Bearer {api_key} +X-API-Key: {api_key} +``` + +El `api_key` es la clave configurada para Palmas360 en el bot. Validar cualquiera de los dos headers es suficiente. + +--- + +## Resumen de endpoints + +| # | Tipo | Endpoint ERP | Descripción | Estado | +|---|------|--------------|-------------|--------| +| 1 | GET | `/fincas` | Lista de fincas activas | Pendiente | +| 2 | GET | `/ciclos/cosecha` | Informe ciclos cosecha | Pendiente | +| 3 | GET | `/ciclos/sanidad/censo` | Informe ciclos censo | Pendiente | +| 4 | GET | `/ciclos/sanidad/plagas` | Informe ciclos plagas | Pendiente | +| 5 | GET | `/ciclos/sanidad/palm` | Informe RHYN. PALM. | Pendiente | +| 6 | GET | `/ciclos/sanidad/tratamientos` | Informe ciclos tratamientos | Pendiente | +| 7 | GET | `/ciclos/polinizacion` | Informe ciclos polinización | Pendiente | +| 8 | GET | `/produccion/kilos-finca` | Kilos facturados por finca | Pendiente | +| 9 | GET | `/produccion/kilos-lotes` | Kilos por lotes (rango fechas) | Pendiente | +| 10 | GET | `/mantenimiento` | Ciclos mantenimiento a la fecha | Pendiente | +| 11 | POST | `/ciclos/cosecha` | Registrar ciclo cosecha | ⚠️ Test | +| 12 | POST | `/ciclos/sanidad` | Registrar ciclo sanidad | ⚠️ Test | +| 13 | POST | `/ciclos/polinizacion` | Registrar ciclo polinización | ⚠️ Test | +| 14 | POST | `/tiquetes` | Registrar tiquete báscula | ⚠️ Test | +| 15 | POST | `/ausentismos` | Registrar ausentismo | ⚠️ Test | +| 16 | POST | `/pluviometria` | Registrar lecturas pluviometría | ⚠️ Test | + +--- + +## Endpoints de DESCARGA (GET) — Bot consulta, ERP responde con archivo + +El bot llama estos endpoints y reenvía la respuesta como documento al usuario de WhatsApp. **La respuesta debe ser un archivo descargable** (PDF o Excel). + +### 1. Lista de fincas + +Usado para mostrar la lista de fincas en flujos dinámicos (Producción kilos por finca, Pluviometría). + +``` +GET {url_base}/fincas +Headers: + Authorization: Bearer {api_key} + X-API-Key: {api_key} +``` + +**Respuesta esperada (JSON, 200):** +```json +[ + { "id": "finca_001", "label": "Finca La Palma" }, + { "id": "finca_002", "label": "Finca El Diamante" }, + { "id": "finca_003", "label": "Finca Los Almendros" } +] +``` + +> El campo `id` es el valor que el bot usará internamente; `label` es lo que ve el usuario en WhatsApp. + +--- + +### 2. Ciclos cosecha + +``` +GET {url_base}/ciclos/cosecha +Headers: + Authorization: Bearer {api_key} + X-API-Key: {api_key} +Query params: + fecha_desde (YYYY-MM-DD) — fecha inicio del período + fecha_hasta (YYYY-MM-DD) — fecha fin del período +``` + +El bot envía automáticamente: +- **"Día actual"** → `fecha_desde` y `fecha_hasta` = hoy +- **"Histórico 30 días"** → `fecha_desde` = hace 30 días, `fecha_hasta` = hoy + +**Respuesta esperada:** Archivo binario (PDF o Excel) +``` +Content-Type: application/pdf +Content-Disposition: attachment; filename="ciclos_cosecha.pdf" +[bytes del archivo] +``` + +--- + +### 3. Ciclos sanidad — Censo + +``` +GET {url_base}/ciclos/sanidad/censo +Headers: + Authorization: Bearer {api_key} + X-API-Key: {api_key} +Query params: + fecha_desde (YYYY-MM-DD) + fecha_hasta (YYYY-MM-DD) +``` + +**Respuesta:** Archivo PDF o Excel. + +--- + +### 4. Ciclos sanidad — Plagas + +``` +GET {url_base}/ciclos/sanidad/plagas +Headers: + Authorization: Bearer {api_key} + X-API-Key: {api_key} +Query params: + fecha_desde (YYYY-MM-DD) + fecha_hasta (YYYY-MM-DD) +``` + +**Respuesta:** Archivo PDF o Excel. + +--- + +### 5. Ciclos sanidad — RHYN. PALM. + +``` +GET {url_base}/ciclos/sanidad/palm +Headers: + Authorization: Bearer {api_key} + X-API-Key: {api_key} +Query params: + fecha_desde (YYYY-MM-DD) + fecha_hasta (YYYY-MM-DD) +``` + +**Respuesta:** Archivo PDF o Excel. + +--- + +### 6. Ciclos sanidad — Tratamientos + +``` +GET {url_base}/ciclos/sanidad/tratamientos +Headers: + Authorization: Bearer {api_key} + X-API-Key: {api_key} +Query params: + fecha_desde (YYYY-MM-DD) + fecha_hasta (YYYY-MM-DD) +``` + +**Respuesta:** Archivo PDF o Excel. + +--- + +### 7. Ciclos polinización + +``` +GET {url_base}/ciclos/polinizacion +Headers: + Authorization: Bearer {api_key} + X-API-Key: {api_key} +Query params: + fecha_desde (YYYY-MM-DD) + fecha_hasta (YYYY-MM-DD) +``` + +**Respuesta:** Archivo PDF o Excel. + +--- + +### 8. Producción kilos por finca + +``` +GET {url_base}/produccion/kilos-finca +Headers: + Authorization: Bearer {api_key} + X-API-Key: {api_key} +Query params: + finca_id — ID de la finca seleccionada por el usuario (viene de /fincas) + fecha_desde (YYYY-MM-DD) + fecha_hasta (YYYY-MM-DD) +``` + +**Respuesta:** Archivo PDF o Excel con kilos facturados para esa finca. + +--- + +### 9. Producción kilos por lotes + +``` +GET {url_base}/produccion/kilos-lotes +Headers: + Authorization: Bearer {api_key} + X-API-Key: {api_key} +Query params: + fecha_desde (YYYY-MM-DD) — ingresada por el usuario + fecha_hasta (YYYY-MM-DD) — ingresada por el usuario +``` + +**Respuesta:** Archivo PDF o Excel con kilos por lote en el rango de fechas. + +--- + +### 10. Mantenimiento + +``` +GET {url_base}/mantenimiento +Headers: + Authorization: Bearer {api_key} + X-API-Key: {api_key} +Query params: + fecha_desde (YYYY-MM-DD) + fecha_hasta (YYYY-MM-DD) +``` + +**Respuesta:** Archivo PDF o Excel con ciclos de mantenimiento. + +--- + +## Endpoints de SUBIDA (POST) — Bot envía datos capturados del usuario ⚠️ + +El bot guía al usuario campo por campo, muestra un resumen, pide confirmación, y luego hace un POST al ERP con los datos. El usuario que envía incluye siempre su número de teléfono y nombre de perfil de WhatsApp. + +**Headers en todos los POST:** +``` +Content-Type: application/json +Authorization: Bearer {api_key} +X-API-Key: {api_key} +``` + +**Respuesta esperada en todos los POST (200):** +```json +{ + "status": "ok", + "message": "Registro guardado correctamente" +} +``` + +Si hay error (400/500): +```json +{ + "status": "error", + "message": "Descripción del error" +} +``` + +--- + +### 11. ⚠️ Registrar ciclo cosecha + +``` +POST {url_base}/ciclos/cosecha +``` + +**Body JSON:** +```json +{ + "fecha": "2026-06-30", + "finca": "La Palma", + "lote": "Lote 3A", + "racimos": "120", + "telefono": "573168950803", + "nombre": "Juan Pérez" +} +``` + +| Campo | Tipo | Descripción | +|-------|------|-------------| +| `fecha` | string (YYYY-MM-DD o texto libre) | Fecha del ciclo ingresada por el usuario | +| `finca` | string | Nombre de la finca | +| `lote` | string | Identificador del lote | +| `racimos` | string | Cantidad de racimos | +| `telefono` | string | Número WhatsApp del usuario que reporta | +| `nombre` | string | Nombre del perfil WhatsApp del usuario | + +--- + +### 12. ⚠️ Registrar ciclo sanidad + +``` +POST {url_base}/ciclos/sanidad +``` + +**Body JSON:** +```json +{ + "fecha": "2026-06-30", + "finca": "La Palma", + "tipo_ciclo": "Censo", + "observaciones":"Sin novedades", + "telefono": "573168950803", + "nombre": "Juan Pérez" +} +``` + +| Campo | Tipo | Descripción | +|-------|------|-------------| +| `fecha` | string | Fecha del ciclo | +| `finca` | string | Nombre de la finca | +| `tipo_ciclo` | string | Tipo de ciclo (Censo, Plagas, RHYN, Tratamiento…) | +| `observaciones` | string | Observaciones libres del usuario | +| `telefono` | string | Número WhatsApp | +| `nombre` | string | Nombre perfil WhatsApp | + +--- + +### 13. ⚠️ Registrar ciclo polinización + +``` +POST {url_base}/ciclos/polinizacion +``` + +**Body JSON:** +```json +{ + "fecha": "2026-06-30", + "finca": "La Palma", + "lote": "Lote 2B", + "palmas_polinizadas": "85", + "telefono": "573168950803", + "nombre": "Juan Pérez" +} +``` + +| Campo | Tipo | Descripción | +|-------|------|-------------| +| `fecha` | string | Fecha del ciclo | +| `finca` | string | Nombre de la finca | +| `lote` | string | Lote trabajado | +| `palmas_polinizadas` | string | Número de palmas polinizadas | +| `telefono` | string | Número WhatsApp | +| `nombre` | string | Nombre perfil WhatsApp | + +--- + +### 14. ⚠️ Registrar tiquete báscula + +``` +POST {url_base}/tiquetes +``` + +**Body JSON:** +```json +{ + "fecha": "2026-06-30", + "numero_tiquete": "T-00452", + "finca": "El Diamante", + "kilos": "3450", + "telefono": "573168950803", + "nombre": "Juan Pérez" +} +``` + +| Campo | Tipo | Descripción | +|-------|------|-------------| +| `fecha` | string | Fecha del tiquete | +| `numero_tiquete` | string | Número del tiquete de báscula | +| `finca` | string | Finca de origen | +| `kilos` | string | Kilos registrados en báscula | +| `telefono` | string | Número WhatsApp | +| `nombre` | string | Nombre perfil WhatsApp | + +--- + +### 15. ⚠️ Registrar ausentismo + +``` +POST {url_base}/ausentismos +``` + +**Body JSON:** +```json +{ + "fecha": "2026-06-30", + "empleado": "Carlos Ramírez", + "motivo": "Incapacidad médica", + "dias": "3", + "telefono": "573168950803", + "nombre": "Juan Pérez" +} +``` + +| Campo | Tipo | Descripción | +|-------|------|-------------| +| `fecha` | string | Fecha de inicio del ausentismo | +| `empleado` | string | Nombre del empleado ausente | +| `motivo` | string | Motivo del ausentismo | +| `dias` | string | Días de ausentismo | +| `telefono` | string | Número WhatsApp | +| `nombre` | string | Nombre perfil WhatsApp | + +--- + +### 16. ⚠️ Registrar pluviometría + +Este endpoint es diferente: el bot pregunta el valor por cada finca (usando la lista de `/fincas`) y envía **un array** con todas las lecturas en una sola llamada. + +``` +POST {url_base}/pluviometria +``` + +**Body JSON:** +```json +{ + "fecha": "2026-06-30", + "telefono": "573168950803", + "nombre": "Juan Pérez", + "lecturas": [ + { "id": "finca_001", "label": "Finca La Palma", "valor": "45" }, + { "id": "finca_002", "label": "Finca El Diamante", "valor": "38" }, + { "id": "finca_003", "label": "Finca Los Almendros", "valor": "52" } + ] +} +``` + +| Campo | Tipo | Descripción | +|-------|------|-------------| +| `fecha` | string | Fecha de la medición | +| `telefono` | string | Número WhatsApp | +| `nombre` | string | Nombre perfil WhatsApp | +| `lecturas[].id` | string | ID de la finca (viene de `/fincas`) | +| `lecturas[].label` | string | Nombre de la finca | +| `lecturas[].valor` | string | Milímetros registrados (texto libre del usuario) | + +--- + +## Formato de respuesta para archivos (endpoints GET) + +El bot espera recibir el archivo directamente en la respuesta HTTP. Formatos soportados: + +| Content-Type | Extensión | Notas | +|---|---|---| +| `application/pdf` | `.pdf` | Preferido para informes | +| `application/vnd.openxmlformats-officedocument.spreadsheetml.sheet` | `.xlsx` | Excel moderno | +| `application/vnd.ms-excel` | `.xls` | Excel legacy | + +**Headers recomendados en la respuesta:** +``` +Content-Type: application/pdf +Content-Disposition: attachment; filename="reporte_cosecha_2026-06-30.pdf" +Content-Length: {tamaño en bytes} +``` + +> Si el archivo pesa más de **16 MB**, WhatsApp rechazará el envío. Para reportes grandes, considerar dividirlos por período o reducir el rango de fechas. + +--- + +## Configuración en el bot + +Una vez que el ERP tenga los endpoints listos, hay que actualizar las URLs en: + +**Admin → Bot Config → Endpoints** (`https://admin.palmas360.com/admin/bot-config?id=2`) + +Los `endpoint_key` que debe buscar y actualizar son: + +| endpoint_key | URL actual (test) | URL real a colocar | +|---|---|---| +| `fincas_list_dn` | — | `{url_base}/fincas` | +| `cosecha_dn` | — | `{url_base}/ciclos/cosecha` | +| `ciclo_censo_dn` | — | `{url_base}/ciclos/sanidad/censo` | +| `ciclo_plagas_dn` | — | `{url_base}/ciclos/sanidad/plagas` | +| `ciclo_palm_dn` | — | `{url_base}/ciclos/sanidad/palm` | +| `ciclo_tratamiento_dn` | — | `{url_base}/ciclos/sanidad/tratamientos` | +| `ciclo_polinizacion_dn` | — | `{url_base}/ciclos/polinizacion` | +| `kilos_finca_dn` | — | `{url_base}/produccion/kilos-finca` | +| `produccion_lotes_dn` | — | `{url_base}/produccion/kilos-lotes` | +| `mantenimiento_dn` | — | `{url_base}/mantenimiento` | +| `ciclos_cosecha_up` | `https://httpbin.org/post` | `{url_base}/ciclos/cosecha` | +| `ciclos_sanidad_up` | `https://httpbin.org/post` | `{url_base}/ciclos/sanidad` | +| `ciclos_polinizacion_up` | `https://httpbin.org/post` | `{url_base}/ciclos/polinizacion` | +| `tiquetes_up` | `https://httpbin.org/post` | `{url_base}/tiquetes` | +| `ausentismos_up` | `https://httpbin.org/post` | `{url_base}/ausentismos` | +| `pluvio_upload` | `https://httpbin.org/post` | `{url_base}/pluviometria` | + +--- + +## Preguntas frecuentes + +**¿Los valores numéricos (kilos, días, racimos) vienen como número o texto?** +Vienen como `string` (texto libre que escribió el usuario). El ERP debe convertirlos al tipo necesario. + +**¿El campo `fecha` está en formato ISO?** +El usuario la escribe libremente (puede ser "30/06/2026", "hoy", "30 de junio"...). Se recomienda que el ERP acepte texto y aplique parsing, o el bot puede configurarse para validar el formato antes de enviar (a coordinar). + +**¿Qué pasa si el ERP responde un error?** +Si el ERP devuelve HTTP 4xx o 5xx, el bot muestra al usuario: *"Hubo un error al enviar los datos. Intenta nuevamente."* + +**¿Cómo se prueba antes de tener el ERP listo?** +Los endpoints de upload actualmente apuntan a `https://httpbin.org/post`, que devuelve el body recibido. Sirve para confirmar que el bot está enviando los datos correctamente. + +**¿Con qué frecuencia llaman los informes?** +Solo cuando el usuario lo solicita manualmente vía WhatsApp. No hay llamadas automáticas o en segundo plano.