BePresent es un sistema de control de asistencia empresarial diseñado para entornos de trabajo remoto. Implementa patrones avanzados de arquitectura como Event Sourcing y Compensating Transactions para garantizar integridad de datos y alta disponibilidad.
- 🔐 Autenticación Segura: Firebase Auth con Google OAuth
- 📊 Event Sourcing: Registro inmutable de todas las operaciones
- 🔄 Reintentos Automáticos: Recuperación ante fallos temporales
- 📧 Alertas Email: Notificaciones en errores críticos
- 📱 Responsive Design: Interface adaptable a móviles y desktop
- 🎨 UI Moderna: TailwindCSS con animaciones fluidas
- ⚡ Real-Time: Sincronización inmediata con Google Sheets
┌─────────────┐
│ Frontend │ ← Firebase Auth + TailwindCSS
│ (Index.html)│
└──────┬──────┘
│ google.script.run
↓
┌─────────────┐
│ Backend │ ← Apps Script + Event Sourcing
│ (Codigo.gs) │
└──────┬──────┘
│
↓
┌─────────────┐
│Google Sheets│ ← Base de datos (3 hojas)
│ Database │
└─────────────┘
Patrones implementados:
- Event Sourcing para auditoría completa
- Compensating Transactions para recuperación automática
- Single Responsibility Principle (SRP)
- Separation of Concerns
Más detalles: ARQUITECTURA.md
BePresent/
│
├── Codigo.gs # Backend (1055 líneas)
│ ├── Configuración global
│ ├── Event Sourcing (Log)
│ ├── Procesamiento de marcaciones
│ ├── Sistema de reintentos
│ └── Alertas y debugging
│
├── Index.html # Frontend (998 líneas)
│ ├── Firebase Auth
│ ├── Dashboard interactivo
│ ├── Lógica de marcaciones
│ └── Sincronización con backend
│
├── ARQUITECTURA.md # Documentación técnica completa
├── DEPLOYMENT.md # Guía de despliegue a producción
├── ESTRUCTURA_SHEETS.md # Estructura de Google Sheets
└── README.md # Este archivo
- Cuenta Google Workspace (@aeropost.com)
- Google Sheets con estructura correcta
- Proyecto Firebase configurado
- Navegador moderno
-
Clonar estructura de Google Sheets:
- Crear hoja con 3 pestañas:
Log,Marcacion,Usuarios - Ver estructura detallada en: ESTRUCTURA_SHEETS.md
- Crear hoja con 3 pestañas:
-
Configurar Backend:
// En Codigo.gs, actualizar: const SPREADSHEET_ID = 'TU_SPREADSHEET_ID_AQUÍ'; const ADMIN_EMAIL = 'tu-email@aeropost.com';
-
Configurar Frontend:
// En Index.html, actualizar Firebase config: const firebaseConfig = { apiKey: "TU_API_KEY", authDomain: "tu-proyecto.firebaseapp.com", // ... };
-
Desplegar Apps Script:
- Abrir Apps Script Editor
- Implementar > Nueva implementación > Web App
- Copiar URL generada
-
Configurar Trigger de Reintentos:
- Apps Script > Triggers > Agregar activador
- Función:
retryFailedEvents - Evento: Time-driven > Every 5 minutes
Guía completa: DEPLOYMENT.md
-
Login:
- Ingresar a URL de la aplicación
- Clic en "Continuar con Google"
- Usar email corporativo @aeropost.com
-
Marcar Asistencia:
- Entrada: Al iniciar jornada laboral
- Salida a Comer: Inicio de almuerzo
- Regreso de Comer: Fin de almuerzo
- Salida: Fin de jornada laboral
-
Visualizar Estado:
- El dashboard muestra horas ya marcadas
- Los botones se habilitan/deshabilitan automáticamente
- Toast confirma cada marcación exitosa
-
Registrar Usuarios:
- Agregar fila en hoja
Usuarios - Incluir: Código, Nombre, Estado, Ubicación, Correo
- Agregar fila en hoja
-
Monitorear Sistema:
- Revisar hoja
Logpara auditoría - Verificar hoja
Marcacionpara registros diarios - Recibir emails en caso de errores críticos
- Revisar hoja
-
Debugging:
// Ejecutar en Apps Script Editor: testConnection() // Verificar configuración testMarcacion() // Simular marcación
Registra todos los eventos del sistema para auditoría completa.
| Columna | Descripción |
|---|---|
| A: ID | Identificador único auto-incremental |
| B: Timestamp | Fecha/hora del evento |
| C: Email | Usuario que realizó la acción |
| D: Nombre | Nombre completo del usuario |
| E: Acción | Entrada / Salida a Comer / Regreso / Salida |
| F: Hora Marcada | Hora formateada (dd/mm/yyyy HH:MM:SS) |
| G: Estado | PENDIENTE / COMPLETADO / ERROR |
| H: Intentos | Contador de reintentos |
| I: Último Intento | Fecha/hora del último reintento |
| J: Mensaje Error | Descripción del error si aplica |
| K: ID Asistencia | Fila afectada en hoja Marcacion |
Una fila por usuario por día. Columnas se llenan progresivamente.
| Columna | Descripción |
|---|---|
| A: Código | Código de empleado |
| B: Nombre | Nombre completo |
| C: Lugar de Marcaje | Ubicación (Home Office) |
| D: Hora de Entrada | Primera marcación del día |
| E: Hora Inicio Almuerzo | Salida a comer |
| F: Hora Retorno Almuerzo | Regreso de comer |
| G: Hora de Salida | Última marcación del día |
| H: Correo | Email (clave de búsqueda) |
Base de datos de empleados autorizados.
| Columna | Descripción |
|---|---|
| A: Código | Código único de empleado |
| B: Nombre | Nombre completo |
| C: Estado | Online / Offline / Break |
| D: Ubicación | Última ubicación conocida |
| E: Correo | Email corporativo @aeropost.com |
Ejemplo: Agregar "Pausa Café"
-
Actualizar constantes en
Codigo.gs:const ACTION_TO_STATE = { // ...existentes 'Pausa Café': 'Break' }; const ACTION_TO_COLUMN = { // ...existentes 'Pausa Café': 8 // Nueva columna I };
-
Agregar columna en Google Sheets (Marcacion)
-
Actualizar Frontend (Index.html):
- Agregar botón
- Agregar handler
- Actualizar lógica de habilitación
const CONFIG = {
MAX_RETRY: 10, // Cambiar de 5 a 10 intentos
RETRY_INTERVAL: 2, // Cambiar de 5 a 2 minutos
DEFAULT_LOCATION: 'Home Office'
};// En procesarMarcacion(), comentar:
// enviarLogsPorEmail(data, result, logId);Causa: Dominio no autorizado en Firebase
Solución:
- Firebase Console > Authentication
- Verificar que Google Sign-In esté habilitado
- Agregar @aeropost.com a dominios autorizados
Diagnóstico:
- Ejecutar
testMarcacion()en Apps Script - Revisar hoja
Logpara ver estado ERROR - Verificar que usuario exista en hoja
Usuarios
Causa: Sincronización con backend fallida
Solución:
- Hacer logout y login nuevamente
- Verificar conexión a internet
- Revisar logs del navegador (F12)
- ARQUITECTURA.md: Arquitectura técnica detallada, patrones de diseño, flujos de datos
- DEPLOYMENT.md: Guía completa de despliegue a producción
- ESTRUCTURA_SHEETS.md: Estructura detallada de Google Sheets
- ✅ Autenticación mediante Firebase Auth
- ✅ Validación de dominio @aeropost.com
- ✅ Permisos de Google Apps Script validados
- ✅ No se almacenan contraseñas (OAuth)
- ✅ Auditoría completa mediante Event Sourcing
- Dashboard de administración
- Reportes mensuales automatizados
- Gráficos de asistencia
- Export a PDF/Excel
- Notificaciones push
- Múltiples ubicaciones de marcaje
- Geolocalización opcional
- App móvil nativa
Este es un proyecto interno de Aeropost. Para sugerencias o reportar bugs, contactar a:
Administrador: caramirez@aeropost.com
- 🐛 FIX CRÍTICO: Validación de timestamps en
updateUserStatus()para prevenir corrupción de estados - ✨ NUEVA FUNCIÓN:
corregirEstadosUsuarios()- Mantenimiento y corrección de estados corruptos - 📧 MEJORA: Emails de diagnóstico con timeline visual, métricas y análisis de integridad
- 🎨 UI: Botones de acceso rápido a formularios (Constancias, Vacaciones, Capacitaciones)
- 🔧 REFACTOR:
updateLogEvent()con búsqueda doble para mayor robustez
Ver detalles completos: CHANGELOG.md
- ✅ Feature: Logs de diagnóstico por email
- 📝 Documentación completa de arquitectura
- 🐛 Fix: Conflicto de nombres de funciones resuelto
- 🐛 Fix: Búsqueda de filas mejorada (multi-columna)
- 🐛 Fix: SyntaxError en línea 392 corregido
- 🎉 Release inicial
- ✅ Event Sourcing completo
- ✅ Compensating Transactions
- ✅ Firebase Auth integrado
- ✅ Interface responsiva
Propiedad de Aeropost. Uso interno exclusivo.
Soporte técnico: caramirez@aeropost.com
Ubicación: Guatemala
Última actualización: 15 de enero de 2026
Versión actual: 1.1.0