diff --git a/README.md b/README.md index 79307ea..cd126ea 100644 --- a/README.md +++ b/README.md @@ -1,326 +1,150 @@ # GLM ID Card Generator -> Herramienta web que permite al equipo de RRHH generar carnets corporativos GLM listos para imprimir en formato CR80 o enviar digitalmente, con verificacion de autenticidad via QR conectado a BambooHR en tiempo real. +## ¿Qué hace este proyecto? + +Sistema de generación de ID corporativas para el departamento de RRHH de GomezLee Marketing (GLM), que opera en 14 países. El sistema permite: + +1. **Generar IDs** (frente y reverso) de empleados de forma individual o por lote (Excel/CSV). +2. **Editar fotos con IA**: usa Google Gemini para vestir al empleado con un uniforme Columbia, bordar el logo de GLM en el pecho derecho y reemplazar el fondo por blanco. +3. **Códigos QR**: cada ID incluye un QR único que redirige a `https://digitalcompass.agency/empleado?id=X` para verificar en tiempo real el estatus del empleado contra BambooHR. +4. **Exportación a PNG**: descarga los ID como PNG listos para impresión CR80 o envío por WhatsApp. +5. **Verificación pública**: cualquier persona puede escanear el QR y ver la foto, nombre, puesto, país y estatus del empleado. + +### Arquitectura + +- **Frontend Generator**: React + Vite (`glm-card-generator/`) +- **Frontend Verificación QR**: React + Vite (`glm-card-qr/`) +- **Workflow de IA**: n8n con Google Gemini para edición de fotos +- **Base de datos**: Supabase (PostgreSQL) +- **Almacenamiento**: Supabase Storage + Google Drive +- **Verificación**: BambooHR API --- -## Informacion General +## Instalación y ejecución -| Campo | Detalle | -|---|---| -| Proyecto | GLM ID Card Generator | -| Area | RRHH — 14 paises | -| Estado | En Progreso | -| Developer Principal | Eidan Then | -| IT Manager | Luis Matos | -| Fecha de Inicio | 2026-06-16 | -| Fecha de Cierre Estimada | 2026-07-28 | -| Ciclo Shape Up | Ciclo 2 — Semana 1 de 6 | -| Board de Ejecucion | https://pmit.digitalcompass.agency/boards/v8iyihdd7u2v | -| PRD del Proyecto | https://docs.google.com/document/d/1SZMEcx5BZGf6CtDk5ZEb08Nx1xMBeyVd9zoqMDFhHgI/edit?usp=sharing | +### Requisitos ---- +- Node.js >= 18 +- npm -## Objetivo - -### Problema que resuelve - -Hoy RRHH depende del area de diseno para generar cada carnet corporativo, lo que toma entre 1 y 3 dias habiles por colaborador. No existe estandar centralizado entre paises ni mecanismo para verificar la autenticidad o el estado activo de un carnet en campo. - -### Solucion implementada - -Un archivo HTML que RRHH abre en cualquier navegador. El operador selecciona el cliente de un desplegable precargado, ingresa los datos del colaborador, sube su foto y descarga dos PNG — frente y reverso — listos para imprimir en CR80 o enviar por WhatsApp. El reverso incluye un QR unico que al escanearse consulta BambooHR en tiempo real y devuelve el estado del colaborador. Para produccion masiva, el operador sube un CSV y el sistema genera todos los carnets en lote dentro de un ZIP. - -### Usuarios y beneficiarios - -- Operador: Equipo de RRHH en los 14 paises de GLM -- Verificador: Supervisores, clientes y auditores que escanean el QR en campo -- Beneficiario: Colaboradores que reciben su carnet impreso o digital - ---- - -## Arquitectura - -### Diagrama de flujo - -``` -MODO INDIVIDUAL -[RRHH abre glm_id_card.html] → [Selecciona cliente / sube logo] → [Ingresa datos + foto] -→ [Sistema genera QR unico con URL de verificacion] → [Vista previa en tiempo real] -→ [Descarga Frente PNG + Reverso PNG con QR] - -MODO BATCH -[RRHH sube CSV] → [Sistema lee cada fila] → [Genera carnet completo por colaborador] -→ [Descarga ZIP con todos los PNG] - -VERIFICACION QR -[Escaneo del QR en campo] → [verify.gomezlee.com/carnet/{ID}] -→ [Endpoint Cloud Run consulta BambooHR API] -→ [Devuelve pagina: Nombre, Puesto, Cliente, Estado (Activo / Inactivo / Terminado)] -``` - -### Stack tecnologico - -| Componente | Tecnologia | Proposito | -|---|---|---| -| Frontend / Generador | HTML5 + CSS3 + JavaScript | Interfaz interactiva del generador — sin frameworks externos | -| Exportacion PNG | html2canvas (libreria JS) | Convierte el DOM del carnet a PNG de alta resolucion para impresion CR80 | -| Generacion de QR | QRCode.js (libreria JS) | Genera el QR unico por colaborador con la URL del endpoint de verificacion | -| Procesamiento batch | JavaScript + FileReader API | Lee el CSV y genera carnets en lote sin intervencion manual por fila | -| Endpoint de verificacion | Python + Google Cloud Run | Recibe el ID del QR, consulta BambooHR y devuelve pagina de estado del colaborador | -| Integracion BambooHR | BambooHR API REST | Fuente de verdad para nombre, puesto, pais, cliente y estado del colaborador | -| Version control | Gitea | Repositorio del generador y del endpoint | - -### Integraciones externas - -| Sistema | Tipo de integracion | Datos que fluyen | -|---|---|---| -| BambooHR | API REST | Nombre, puesto, pais, cliente asignado, estado del empleado (activo / inactivo / terminado) | -| Google Cloud Run | Endpoint HTTP publico | Recibe ID del colaborador desde el QR y devuelve pagina de verificacion | -| CSV local | Archivo de entrada | Nombre, puesto, pais, cliente, id_colaborador, ruta_foto (opcional) | - ---- - -## Configuracion y Setup - -### Prerequisitos - -- [ ] Acceso a BambooHR API (API Key del subdominio GLM) -- [ ] Proyecto configurado en Google Cloud con Cloud Run habilitado -- [ ] Variable de entorno `BAMBOOHR_API_KEY` configurada en Cloud Run -- [ ] Variable de entorno `BAMBOOHR_SUBDOMAIN` configurada en Cloud Run -- [ ] Dominio `verify.gomezlee.com` apuntando al servicio de Cloud Run -- [ ] Lista de clientes precargados definida y aprobada por RRHH (nombre + logo PNG) - -### Variables de entorno - -| Variable | Descripcion | Donde se obtiene | -|---|---|---| -| `BAMBOOHR_API_KEY` | API Key de BambooHR | BambooHR → Admin → API Keys | -| `BAMBOOHR_SUBDOMAIN` | Subdominio de la cuenta GLM en BambooHR | URL de BambooHR: {subdominio}.bamboohr.com | -| `VERIFY_BASE_URL` | URL base del endpoint de verificacion | Ej: https://verify.gomezlee.com | - -> Las credenciales nunca se commitean al repo. Todas las keys van en el vault de credenciales GLM o en los secrets de Google Cloud Run. - -### Instalacion — Endpoint de verificacion +### 1. Clonar el repositorio ```bash -# Clonar el repo -git clone https://gitea.glm.com/glm-it/glm-id-card-generator - -# Instalar dependencias del endpoint -cd endpoint/ -pip install -r requirements.txt --break-system-packages - -# Configurar variables de entorno locales para pruebas -cp .env.example .env -# Editar .env con las credenciales reales - -# Correr el endpoint en local -python main.py - -# Deploy a Google Cloud Run -gcloud run deploy glm-id-card-verify \ - --source . \ - --region us-central1 \ - --allow-unauthenticated +git clone +cd GLM ID Card Generator ``` -### Distribucion del generador HTML - -El archivo `glm_id_card.html` se distribuye directamente a RRHH via email o carpeta compartida. No requiere instalacion. El operador lo abre en Chrome o Edge. - ---- - -## Como funciona - -### Flujo paso a paso — Modo individual - -1. El operador abre `glm_id_card.html` en Chrome o Edge -2. Selecciona el cliente del desplegable precargado (o sube un logo nuevo) -3. Ingresa nombre completo, puesto, pais e ID del colaborador -4. Sube la foto del colaborador — aparece recortada en circulo en el frente -5. El sistema genera automaticamente el QR con la URL `verify.gomezlee.com/carnet/{ID}` -6. El operador visualiza la vista previa en tiempo real del frente y el reverso -7. Descarga el Frente PNG y el Reverso PNG por separado -8. Envia los PNG al colaborador o los imprime en formato CR80 - -### Flujo paso a paso — Modo batch - -1. El operador prepara el CSV segun el formato requerido (ver seccion Formato CSV) -2. Sube el CSV al generador -3. El sistema procesa cada fila, genera el carnet completo y produce un ZIP -4. El ZIP contiene los archivos nombrados como `{nombre_colaborador}_frente.png` y `{nombre_colaborador}_reverso.png` - -### Flujo de verificacion QR - -1. Supervisor o cliente escanea el QR del reverso del carnet con cualquier telefono -2. El QR abre `verify.gomezlee.com/carnet/{ID_COLABORADOR}` en el navegador del telefono -3. El endpoint consulta BambooHR con el ID del colaborador -4. Se devuelve una pagina web con: nombre, puesto, cliente, pais y estado del colaborador -5. Si el colaborador esta activo: pagina verde con sus datos completos -6. Si el colaborador esta inactivo o terminado: pagina roja con mensaje "Carnet no vigente" - -### Formato CSV para batch - -| Columna | Requerida | Descripcion | -|---|---|---| -| `nombre_completo` | Si | Nombre completo del colaborador | -| `puesto` | Si | Puesto o cargo | -| `pais` | Si | Pais de operacion | -| `cliente` | Si | Nombre del cliente (debe coincidir exactamente con la lista precargada) | -| `id_colaborador` | Si | ID del colaborador en BambooHR | -| `ruta_foto` | No | URL publica de la foto. Si se omite, el circulo de foto queda vacio | - -### Schedules y triggers - -| Trigger | Descripcion | -|---|---| -| Manual — abre el HTML | El operador genera carnets cuando RRHH lo necesita | -| Escaneo del QR | El endpoint se dispara on-demand cada vez que alguien escanea un carnet en campo | - ---- - -## Testing - -### Como probar el sistema +### 2. Configurar variables de entorno ```bash -# Test unitario del endpoint -cd endpoint/ -python -m pytest tests/ +# Para el generador de IDs +cp glm-card-generator/.env.example glm-card-generator/.env -# Test de integracion — verificacion real contra BambooHR -python tests/test_bamboohr_integration.py - -# Test manual del generador HTML -# 1. Abrir glm_id_card.html en Chrome -# 2. Llenar todos los campos con datos de prueba -# 3. Exportar PNG y verificar dimensiones: 1012 x 638 px a 96 dpi display (equivalente a 300 dpi en CR80) -# 4. Imprimir en hoja CR80 y verificar calidad -# 5. Escanear el QR generado y confirmar que abre el endpoint correctamente +# Para el visor QR +cp glm-card-qr/.env.example glm-card-qr/.env ``` -### Casos de prueba minimos +Editar los archivos `.env` con los valores correspondientes. -| Caso | Input | Output esperado | Estado | -|---|---|---|---| -| Carnet individual completo | Todos los campos + foto + cliente seleccionado | PNG frente y reverso descargados correctamente | Pendiente | -| Carnet sin foto | Todos los campos sin foto | PNG generado con circulo vacio en frente | Pendiente | -| Batch CSV valido | CSV con 20 colaboradores | ZIP con 40 PNG (frente + reverso por colaborador) en menos de 2 minutos | Pendiente | -| QR colaborador activo | ID valido en BambooHR, estado activo | Pagina verde con datos completos del colaborador | Pendiente | -| QR colaborador inactivo | ID valido en BambooHR, estado inactivo | Pagina roja con mensaje "Carnet no vigente" | Pendiente | -| QR ID inexistente | ID que no existe en BambooHR | Mensaje de error claro, sin crash del endpoint | Pendiente | -| Cliente nuevo con logo manual | Logo subido manualmente sin seleccionar del desplegable | Logo aparece correctamente en el reverso del PNG | Pendiente | -| BambooHR API caida | Timeout del endpoint al consultar BambooHR | Mensaje de error legible, endpoint no crashea | Pendiente | +### 3. Instalar dependencias y ejecutar ---- - -## Errores conocidos y troubleshooting - -| Error | Causa probable | Solucion | -|---|---|---| -| QR no abre la pagina de verificacion | Dominio verify.gomezlee.com no apunta a Cloud Run | Verificar DNS y configuracion del servicio en Google Cloud Run | -| PNG exportado se ve diferente al preview | html2canvas no soporta alguna propiedad CSS usada | Revisar consola del navegador, simplificar el estilo CSS del elemento afectado | -| Endpoint devuelve 401 | API Key de BambooHR vencida o incorrecta | Renovar la API Key en BambooHR y actualizar el secret en Google Cloud Run | -| Batch no genera todos los carnets | Fila del CSV con campo obligatorio vacio | Revisar el CSV — todas las columnas requeridas deben tener valor en cada fila | -| Logo del cliente no aparece en el PNG | Logo en formato no soportado o con CORS bloqueado | Usar PNG con fondo transparente, minimo 300px de ancho, hosteado en el mismo dominio o con CORS abierto | -| Endpoint lento al responder | BambooHR API con latencia alta | El endpoint tiene cache de 5 minutos por ID — si es la primera consulta puede tardar hasta 3 segundos | - ---- - -## Monitoreo - -- **Google Cloud Run Logs:** Revisar logs del servicio `glm-id-card-verify` en Google Cloud Console para errores del endpoint -- **BambooHR API:** Si el endpoint falla consistentemente, verificar el estado de la API de BambooHR y los limites de rate limit -- **Output esperado:** El endpoint debe responder en menos de 3 segundos. Si supera ese tiempo de forma sistematica, revisar la implementacion del cache. - ---- - -## Estructura del repositorio +**Generador de IDs:** +```bash +cd glm-card-generator +npm install +npm run dev ``` -/glm-id-card-generator -├── README.md <- Este archivo -├── glm_id_card.html <- Generador de carnets (distribuir a RRHH) -├── /assets -│ ├── /logos-clientes <- Logos PNG de clientes precargados (aprobados por RRHH) -│ └── glm-logo.png <- Logo GLM para el generador -├── /endpoint -│ ├── main.py <- Punto de entrada del servicio de verificacion -│ ├── requirements.txt <- Dependencias Python del endpoint -│ ├── .env.example <- Variables de entorno de ejemplo (sin valores reales) -│ ├── Dockerfile <- Para deploy en Google Cloud Run -│ └── /tests -│ ├── test_endpoint.py <- Tests unitarios del endpoint -│ └── test_bamboohr_integration.py <- Tests de integracion con BambooHR API -├── /batch -│ └── ejemplo_colaboradores.csv <- CSV de ejemplo con el formato requerido para batch -├── /docs -│ ├── guia-uso-rrhh.pdf <- Guia de uso para operadores de RRHH -│ └── architecture.png <- Diagrama de arquitectura del sistema -├── CHANGELOG.md <- Historial de cambios -└── DECISIONS.md <- Log de decisiones tecnicas + +Abre en: `http://localhost:5173/empleado-id/` + +**Visor QR:** + +```bash +cd glm-card-qr +npm install +npm run dev +``` + +Abre en: `http://localhost:5173/empleado` + +### 4. Build para producción + +```bash +# Generador +cd glm-card-generator +npm run build +# El output está en glm-card-generator/dist/ + +# Visor QR +cd glm-card-qr +npm run build +# El output está en glm-card-qr/dist/ ``` --- -## CHANGELOG +## Variables de entorno -``` -[2026-07-28] v1.0 — Launch inicial en produccion +### `glm-card-generator/.env.example` + +```env +VITE_SUPABASE_ANON_KEY=J5JS7HG... +VITE_SUPABASE_URL=https://tudominio +VITE_WEBHOOK_TOKEN=6d4g56d4fgd... +VITE_N8N_WEBHOOK_URL=https://tudominio/webhook/carnet ``` ---- +### `glm-card-qr/.env.example` -## DECISIONS LOG +```env +VITE_SUPABASE_URL=https://tudominio +VITE_SUPABASE_ANON_KEY=J5JS7HG... +``` -### DEC-001 — Generador como HTML local vs. app web hosteada +### Descripción de variables -- Fecha: 2026-06-16 -- Contexto: Se evaluo si el generador debia ser una app web hosteada en Google Cloud o un archivo HTML distribuido localmente a RRHH. -- Opciones consideradas: App web hosteada (requiere autenticacion, servidor, mantenimiento) vs. HTML local (distribucion simple, sin dependencias de red para generar el carnet). -- Decision: HTML local distribuido a RRHH en Fase 1. -- Razon: El equipo de RRHH opera en 14 paises con distintos niveles de conectividad. El HTML local garantiza que el generador funciona sin internet. Solo el endpoint de verificacion QR requiere conexion. - -### DEC-002 — Verificacion QR via BambooHR en tiempo real vs. base de datos propia - -- Fecha: 2026-06-16 -- Contexto: Se evaluo mantener una base de datos propia en Supabase con el estado de cada carnet vs. consultar BambooHR directamente al momento del escaneo. -- Opciones consideradas: Base de datos propia (requiere sincronizacion manual o automatica con BambooHR) vs. BambooHR como fuente de verdad (estado siempre actualizado, sin base de datos adicional). -- Decision: BambooHR como fuente de verdad con consulta en tiempo real. -- Razon: Elimina el riesgo de datos desincronizados. Cuando RRHH da de baja a un colaborador en BambooHR, el QR lo refleja de inmediato sin ningun paso adicional. +| Variable | Descripción | +|---|---| +| `VITE_SUPABASE_URL` | URL del proyecto Supabase | +| `VITE_SUPABASE_ANON_KEY` | Clave anónima de Supabase | +| `VITE_WEBHOOK_TOKEN` | Token de autenticación para el webhook de n8n | +| `VITE_N8N_WEBHOOK_URL` | URL del webhook en n8n (`/webhook/carnet`) | --- -## Contactos del proyecto +## Explicación del workflow de n8n -| Rol | Nombre | Contacto | -|---|---|---| -| Product Owner | Maximo Gomez | [email/WhatsApp] | -| IT Manager | Luis Matos | [email/WhatsApp] | -| Developer Principal | Eidan Then | [email/WhatsApp] | +**Archivo**: `n8n-workflow/GLM ID Card Generator.json` ---- +El workflow **"GLM ID Card Generator"** se ejecuta cuando el frontend envía una foto de empleado al webhook `POST /webhook/carnet` autenticado con el token en el header. -## Definition of Done +### Flujo -Checklist antes de mover a Completado en Kan.bn: +1. **Webhook** — Recibe la solicitud POST con la foto del empleado (y opcionalmente un array de empleados para lote). +2. **IF: "Es un binario y employeeId?"** — Determina si es un envío individual (tiene `employeeId` y foto binaria) o por lote. +3. **IF: "Es un binario?"** — Verifica si el body contiene `empleados` (array de empleados en modo lote). +4. **Split Out** + **Loop Over Items** — En modo lote, separa el array y procesa cada empleado uno por uno. +5. **Download file** (Google Drive) — Descarga la foto del empleado desde Google Drive (según URL recibida). +6. **Descargar logo GLM** (HTTP Request) — Obtiene el logo de GLM desde Supabase Storage. +7. **Edit an image (Google Gemini)** — Edita la foto del empleado con IA: + - Modelo: `gemini-3-pro-image` o `gemini-3.1-flash-image` + - Viste a la persona con un uniforme Columbia (camisa de botones color `#2d3748`) + - Borda el logo de GLM en el pecho derecho + - Reemplaza el fondo por blanco sólido +8. **Extract from File** — Extrae el binario de la imagen editada. +9. **Guardar foto** (Google Drive) — Guarda la foto editada en la carpeta "Fotos Temporal Carnet Empleados". +10. **Hacer url publica** (Google Drive) — Comparte la imagen públicamente. +11. **Actualizar foto del empleado** (Supabase) — Actualiza el registro del empleado en la tabla `empleados_glm` con la `photo_url` y marca `photo_uploaded = FALSE`. +12. **Merge** — Combina los resultados. +13. **Respond to Webhook** — Devuelve la URL de la foto editada al frontend. -- [ ] Todos los criterios de exito cumplidos y verificados -- [ ] PNG exportado validado fisicamente en impresion CR80 -- [ ] Modo batch probado con CSV de al menos 20 colaboradores -- [ ] QR escaneado y verificacion confirmada contra BambooHR en ambiente real -- [ ] Endpoint de verificacion desplegado en Google Cloud Run y accesible publicamente -- [ ] Generador probado en Chrome y Edge en al menos 2 paises -- [ ] Lista de clientes precargados cargada y validada con RRHH -- [ ] Codigo commiteado y pusheado a Gitea -- [ ] README completo y actualizado -- [ ] Variables de entorno documentadas en `.env.example` -- [ ] Prueba de usuario real con al menos un miembro del equipo RRHH -- [ ] Luis Matos valido el output tecnico -- [ ] Maximo aprobo el resultado final +### Credenciales usadas ---- - -_Documento mantenido por el equipo GLM IT · Ultima actualizacion: 2026-06-05_ \ No newline at end of file +| Tipo | Nombre | +|---|---| +| HTTP Header Auth | GLM ID Generator | +| Google Drive OAuth2 | Eidan - Google Drive account | +| Google Gemini API | Eidan - Google Gemini(PaLM) Api account | +| Supabase API | Sofia test - Supabase account |